Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SpringBoot应用程序中的Mockito Mock和Spy_Java_Unit Testing_Spring Boot_Junit_Mockito - Fatal编程技术网

Java SpringBoot应用程序中的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

我已经读了不少文章/博客/StackOverflow问题,但关于Mockito mock和spy的困惑仍然存在。因此,我开始尝试在一个小型的
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注释为什么不受欢迎?