Java SpringBoot应用程序中的Mockito Mock和Spy
我已经读了不少文章/博客/StackOverflow问题,但关于Mockito mock和spy的困惑仍然存在。因此,我开始尝试在一个小型的Java SpringBoot应用程序中的Mockito Mock和Spy,java,unit-testing,spring-boot,junit,mockito,Java,Unit Testing,Spring Boot,Junit,Mockito,我已经读了不少文章/博客/StackOverflow问题,但关于Mockito mock和spy的困惑仍然存在。因此,我开始尝试在一个小型的springboot应用程序中实现它们。我的应用程序有一个ProductRepository扩展crudepository 目前,我正在模拟ProductRepository测试存储库,如下所示 @RunWith(SpringRunner.class) @SpringBootTest(classes = {RepositoryConfiguratio
springboot
应用程序中实现它们。我的应用程序有一个ProductRepository
扩展crudepository
目前,我正在模拟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
,为什么我需要它?任何与此相关的特定场景都是最受欢迎的
提前感谢。我已经看了您的测试,没有什么需要记住的(这是基于我的经验,所以最后的电话由您决定): 1)Hamcrest-如果可能的话,我强烈建议在assert实现中使用Hamcrest。 首先,它比标准junit断言更通用,功能更丰富。 其次,有一天您可能需要(就像我在一个项目中所做的那样)从junit切换到examle的testng。 如果所有断言都基于xunit中立的实现,那么切换就不会那么痛苦了 2)断言-代替
assertNull
,assertEquals
使用hamcrest的assertThat(字符串描述、T值、matcher匹配器)代码>
由于这一点,当测试中断时,您将获得清晰的错误消息
3)小测试-在您的存储库测试中。。不要将所有案例放在一个测试中。
尝试为以下情况创建许多小而简单的测试:findOne。。计数芬德尔等。
同样,当这样的小测试失败时,发现问题会更容易。
如果有更多的案例出现,你不会得到一个200多行的测试案例,这是不可接受的
4)命名-不要将测试命名为。。testXYZ。
很明显,这些都是测试方法。
我建议使用BDD命名方式:shouldX\u whenY\u givenZ
。
F.e.应返回零计数(如果数据库中没有实体)
5)结构-尝试将每个测试实现分为三个明确的部分,包括获得最佳结果的注释:
public void should..() throws Exception{
// Arrange
// when().then()
// mock()
// Act
// classUnderTest.process()
// Assert
// assertThat(..)
}
6)不要在模拟/间谍测试之间分割测试类。做一次测试
7)永远不要模仿正在测试的类。在最坏的情况下,如果必须模拟被测试类的某些方法,请使用Spy。
模拟的要点是隔离被测试类中的实现,以便在测试期间仅调用该类逻辑。
仅模拟类的依赖项。不要对存储库进行单元测试。。关注与单元测试相关的服务层。如果你的存储库中有一些逻辑,那么这可能是一个设计缺陷。是的,明白了。谢谢。@Maciej Kowalski终于根据您的输入使用模拟和间谍来测试服务层。但我不知道我是否做对了,我的回购是在你的观察将是有价值的。如果需要,可以将此作为问题发布。谢谢。我查过回购协议。。请参阅我的回答:与使用构造函数/设置器方法使用mock初始化测试对象相比,InjectMock注释为什么不受欢迎?