代码之家  ›  专栏  ›  技术社区  ›  Johan Fredin

单元测试断言vs mockito.verify()

  •  1
  • Johan Fredin  · 技术社区  · 6 年前

    摆弄Mockito来实现我的服务的单元测试,但是由于某些原因,我无法通过我的厚头骨来实现这一点。我的考试通过了,但我不相信我做得对。

    下面是一个测试count()方法的示例。方法只是将调用转发到它的存储库,我不想验证是否只会发生这种情况。这就是我得到的:

    @RunWith(MockitoJUnitRunner.class)
    public class PersonServiceImplTest {
    
        @Mock
        private PersonRepository personRepository;
    
        @InjectMocks
        private PersonServiceImpl personService;
    
        @Test
        public void testCount() {
    
            when(personRepository.count()).thenReturn(2L);
    
            long count = personService.count();
    
            assertEquals(2L, count);
    
            verify(personRepository).count();
        }
    }
    

    我的考试通过了,但我有一些问题。

    1. 是否需要断言等于?据我所知,作为方法存根(.thenReturn(value..))的预期结果而放置的任何内容都将始终是返回的值。或者在这种情况下它可能是其他什么东西?

    2. 我需要验证吗?我想这样做是因为我想验证PersonRepository.Count()实际上是被调用的。或者当我有assertEquals()时,这也是多余的吗?

    3. 我需要断言等于和验证吗?

    4. 最后,我做得对吗?)

    谢谢你

    3 回复  |  直到 6 年前
        1
  •  2
  •   starf    6 年前

    是的,你做得对。

    您正在将一个模拟存储库注入到一个真正的服务中,然后测试该服务。当涉及到您服务中的业务逻辑时,任何事情都可能发生。这就是为什么使用已知的输入和输出来验证代码是很重要的,就像您所做的那样。

    1. 考虑到存储库的响应,您正在检查业务逻辑的结果。这个特定的代码相当简单,但是想象一下,如果业务逻辑提供的是一个平均值或一个和,而不仅仅是存储库提供的相同值。

    2. 3。verify和assertequals正在测试不同的东西。验证检查是否调用了存储库方法,断言检查服务是否用正确的值响应。假设您的服务方法有一个硬编码 return 2L . 断言等于将通过,但验证将失败。

    3. 是的,你做得对。你测试的内容与你测试的原因有关。是否需要特定的断言或验证通常取决于具体情况。在这种情况下,您的存储库方法返回的测试几乎没有意义 2L ,但有一个很好的例子可以测试您的服务是否返回 2L . 类似地,在测试中没有必要调用服务方法,但是有一个很好的例子可以测试是否调用了存储库方法。

    现在您有了测试服务的工具,下一步是确定要编写哪些测试。

        2
  •  3
  •   MyStackRunnethOver Khanna111    6 年前

    整齐:

    1. assertEquals() 需要: 这要看情况而定。有什么事要做的结果是 personRepository.count() 在里面 personService 在返回之前,是否有可能更改其值?如果答案是“绝对不是”,那么你可能不需要 断言QualSQL() -但是如果有什么可能出错的话 断言QualSQL() 一定不会。

    2. 你需要 verify() : 这要看情况而定。有没有可能 个人存储库.count() 不叫?或者不止一次( VIFIFY() 默认情况下,它的参数只需要调用一次?如果不是,那么你可能不需要它。

    3. 是否需要两个: 这取决于(注意到模式?).看上面:他们做不同的事情。在许多情况下,您都希望检查这两件事:1。返回正确的结果,和2。通过做你期望做的事情来返回结果。

    4. 你做得对吗? 好。。。这要看情况而定。做 个人存储库.count() 看起来像

      public int count() {
          return this.personService.count();
      }
      

    如果是这样,您可能根本不需要进行太多的测试。如果你坚持要考试,跳过 VIFIFY() 可能没问题,因为上面的方法 没有其他方法获得价值 而不是通过调用函数 verify 它返回这个值,所以几乎不能多次调用它。

    另一方面,如果您的函数如下所示:

    public int count() {
        // get a personService from an injector
        // log the personService's details
        // generate a random number
        // try calling count() on personService, catch an error
        // if you caught the error, return the random number
    }
    

    那么也许你 VIFIFY() 因为突然之间,发生了很多事情,其中一些事情(即随机数)可能会被混淆,从而导致功能正常,即使某些事情发生了严重的错误。

        3
  •  0
  •   chrylis -cautiouslyoptimistic-    6 年前

    最好注射 PersonRepository 通过构造函数而不是 @InjectMocks . 这也消除了对特定的运行程序的需要(或者在稍后的测试中,涉及低级测试的Spring)。

    你对mockito的使用是 对的 但不是最佳的。你确实需要 assertEquals 因为你测试的是 服务 返回与从存储库中提供的值相同的值。这个 verify...count 不是必需的,因为它是通过检查是否返回了适当的值来暗示的。您可以通过返回随机数而不是 2 .

    还要检查它是否真的值得包装 count() 在另一个对象中,或者只是添加不必要的层。

    最后,你可以考虑检查 Spock 它是一种基于JUnit之上的基于groovy的测试语言,它提供了一种干净而强大的模拟语言。