如何验证方法是否已被Mockito调用

时间:2019-04-10 15:31:25

标签: java unit-testing spring-boot junit mockito

我正在尝试模拟在另一个方法中调用的方法的行为,以便它模拟对象的返回,而在另一次方法引发异常时,则不进行模拟,但是否准确以及是否可能可能。

@Service
@Transactional
public class CategoryService {

    @Autowired
    private CategoryRepository repository;

    public Category findById(Integer id) {
        Optional<Category> obj = repository.findById(id);
        return obj.orElseThrow(() -> new ObjectNotFoundException(id.toString()));
    }


    public Category update(Category category){
        // Throws ObjectNotFoundException if not found before update
        this.findById(category.getId());
        return repository.save(category);
    }

}


@RunWith(MockitoJUnitRunner.class)
public class CategoryServiceUnitTest {

    @Mock
    private CategoryService service;

    @Test()
    public void Should_UpdateCategory_When_FindCategory() {
        Category cat = new Category(1, "Test");
        //Is it possible?
        when(service.findById(Mockito.anyInt())).thenReturn(cat);

        Category category = service.update(cat);
        assertThat(category.getName()).isEqualTo(cat.getName());

        verify(service, times(1)).update(cat);
    }

    @Test(expected = ObjectNotFoundException.class)
    public void Should_ThrowsObjectNotFoundException_When_NotFoudCategoryById() {
        Category cat = new Category(1, "Test");
        //Is it possible?
        when(service.findById(Mockito.anyInt())).thenThrow(ObjectNotFoundException.class);

        service.update(cat);
    }

}

1 个答案:

答案 0 :(得分:0)

正如评论中指出的那样,您想要做的是在测试中模拟CategoryRepository

@RunWith(MockitoJUnitRunner.class)
public class CategoryServiceTest {

    private CategoryService service;

    @Mock
    private CategoryRepository repository;

    @Before
    public void setup() {
        service = spy(new CategoryService(repository));
    }

    @Test
    public void Should_UpdateCategory_When_FindCategory() throws ObjectNotFoundException {
        Category cat = new Category(1, "Test");

        when(repository.findById(Mockito.anyLong())).thenReturn(Optional.of(cat));
        //return the category object that is used to call the repository.save(...) method
        when(repository.save(Mockito.any(Category.class)))
                .thenAnswer((Answer<Category>) invocation -> {
                            Object[] args = invocation.getArguments();
                            return (Category) args[0];
                        }
                );
        //depending on your requirements the above might be overkill, just replace that logic with this
        //when(repository.save(Mockito.any(Category.class))).thenReturn(cat);

        Category category = service.update(cat);

        assertThat(category).isNotNull();
        assertThat(category.getName()).isEqualTo(cat.getName());

        verify(service).update(cat);
    }

    @Test(expected = ObjectNotFoundException.class)
    public void Should_ThrowsObjectNotFoundException_When_NotFoudCategoryById() throws ObjectNotFoundException {
        Category cat = new Category(1, "Test");

        when(service.findById(Mockito.anyLong())).thenThrow(ObjectNotFoundException.class);

        service.update(cat);
    }
}

您还需要处理已检查的异常ObjectNotFoundException。我刚刚将异常添加到方法签名中,您可能希望在生产设置中以不同的方式处理它

@Service
@Transactional
public class CategoryService {

    private final CategoryRepository repository;

    @Autowired
    public CategoryService(CategoryRepository repository) {
        this.repository = repository;
    }

    public Category findById(Long id) throws ObjectNotFoundException {
        Optional<Category> obj = repository.findById(id);
        return obj.orElseThrow(() -> new ObjectNotFoundException(id.toString()));
    }

    public Category update(Category category) throws ObjectNotFoundException {
        // Throws ObjectNotFoundException if not found before update
        this.findById(category.getId());
        return repository.save(category);
    }
}