我已经阅读了不少文章/博客/ StackOverflow问题,但关于Mockito模拟和间谍的困惑仍然存在。所以,我开始尝试在一个小Spring Boot
应用中实现它们。我的应用有ProductRepository
个CrudRepository
。
目前我正在通过模拟ProductRepository
来测试存储库,如下所示
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {RepositoryConfiguration.class})
public class ProductRepositoryMockTest {
@Mock
private ProductRepository productRepository;
@Mock
private Product product;
@Test
public void testMockCreation(){
assertNotNull(product);
assertNotNull(productRepository);
}
@Test
public void testSaveProduct() {
assertThat(product.getId(), is(equalTo(0)));
when(productRepository.save(product)).thenReturn(product);
productRepository.save(product);
//Obviously this will fail as product is not saved to db and hence
//@GeneratedValue won't come to play
//assertThat(product.getId() , is(not(0)));
}
@Test
public void testFindProductById() {
when(productRepository.findOne(product.getId())).thenReturn(product);
assertNotNull(productRepository.findOne(product.getId()));
assertEquals(product, productRepository.findOne(product.getId()));
}
}
测试通过。这是正确的方法吗?我还想了解如何在这里使用@Spy
以及为什么需要它?任何与此相关的特定场景都是最受欢迎的。
提前致谢。
答案 0 :(得分:2)
我已经看了你的测试,并且有一些事情要记住(这是基于我的经验,所以最后的电话由你决定):
1)Hamcrest - 如果可能的话,我强烈建议您使用Hamcrest进行断言实现。 首先,它比标准的junit断言更通用,功能更丰富。 其次,你可能有一天需要(就像我在其中一个项目中所做的那样)从junit切换到testng进行检查。 将所有断言都基于xunit-neutral实现,交换机不会那么痛苦。
2)断言 - 而不是assertNull
,assertEquals
代替hamcrest的assertThat(String description, T value, Mathcer<T> matcher);
因此,当测试中断时,您将收到明确的错误消息。
3)小测试 - 在您的存储库测试中..不要将所有案例都放在一个测试中。 尝试为以下情况创建许多小而简单的测试:findOne .. count .. findAll等。 再次,当这样的小测试中断时,更容易找到问题。 如果有更多的案例,你将不会得到200多行测试用例,这是不可接受的
4)命名 - 不要将测试命名为.. testXYZ。
很明显,这些是测试方法。
我建议使用BDD命名方式:shouldX_whenY_givenZ
。
F.E. shouldReturnZeroCount_givenNoEntitiesInTheDatabase
5)结构 - 尝试将每个测试实现拆分为三个显式部分,包括最佳结果的注释:
public void should..() throws Exception{
// Arrange
// when().then()
// mock()
// Act
// classUnderTest.process()
// Assert
// assertThat(..)
}
6)不要在Mock / Spy测试之间拆分测试类。有一个ImplTest。
7)永远不要模拟您正在测试的课程。在最坏的情况下,如果你必须模拟被测试类的一些方法,请使用Spy。 模拟的目的是隔离被测试类中的实现,以便在测试期间仅调用类逻辑。 模拟只有类的依赖。