java - Spring Boot 应用程序中的 Mockito 模拟和 spy

标签 java unit-testing spring-boot junit mockito

我已经阅读了很多文章/博客/StackOverflow 问题,但是关于 Mockito 模拟和 spy 的困惑仍然存在。所以,我开始尝试在一个小的 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在这里,我为什么需要它?任何与此相关的特定场景都是最受欢迎的。

提前致谢。

最佳答案

我看过你的测试,有几件事要记住(这是基于我的经验,所以最后的决定取决于你):

1) Hamcrest - 如果可能的话,我强烈建议您将 Hamcrest 用于您的断言实现。
首先,它比标准的 junit 断言更加通用和功能丰富。
其次,你可能有一天需要(就像我在我的一个项目中所做的那样)例如从 junit 切换到 testng。
拥有基于 xunit 中性实现的所有断言,切换不会那么痛苦。

2) 断言 - 而不是 assertNull , assertEquals去hamcrest的assertThat(String description, T value, Mathcer<T> matcher); 多亏了这一点,您将在测试中断时收到清晰的错误消息。

3)小测试 - 在您的存储库测试中......不要将所有案例都放在一个测试中。
尝试为以下情况创建许多小而简单的测试:findOne..count..findAll 等。
同样,当像这样的小测试中断时,会更容易找到问题。
如果会有更多的案例出现,您最终不会得到 200 多行测试用例,这是 Not Acceptable

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) 永远不要 mock 您正在测试的类(class)。在最坏的情况下,如果您必须模拟被测类的某些方法,请使用 Spy。
模拟的重点是隔离被测类中的实现,以便在测试期间只调用类逻辑。
仅模拟类的依赖项。

关于java - Spring Boot 应用程序中的 Mockito 模拟和 spy ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42394958/

相关文章:

java - 在 JDBC 中处理 Oracle 的 "Timestamp With local TimeZone"数据类型

java - Spring Controller 的 catch block 中的单元测试代码

Spring Security OAuth2 accessToken

java - Eclipse 中的 JADE ICP 异常

java - Java7中方法句柄的用途是什么?

java - Android - 任务 ':app:compileDebugJava' 执行失败,预期为 ';'

python - PyCharm - 没有找到测试?

unit-testing - 在生产代码中提取类后是否应该创建新的测试类?

java - .properties 文件中的 Spring Boot OAuth2 安全属性名称?

java - org.springframework.data.domain.PageImpl 无法转换为