这个使用模拟对象的Spring单元测试究竟如何工作?

时间:2014-11-23 17:11:18

标签: java spring junit mocking easymock

我正在攻读Spring Core认证,我对在JUnit测试中使用 mock 有一些疑问。

我知道,不同于我必须实现接口来创建假对象(我的存根)的存根,使用模拟我使用模拟框架(作为 EasyMock )为我生成一个在我的测试中使用的模拟对象。

因此,使用mock进行测试的步骤如下:

  1. 使用模拟库生成即时实现从属接口的模拟对象

  2. 记录模拟,期望它将如何用于场景:将调用哪些方法返回的值

    < / LI>
  3. 练习场景

  4. 验证模拟期望是否得到满足

  5. 例如,我可以拥有以下测试类:

    import static org.easymock.classextensions.EasyMock.*;
    
    public class AuthenticatorImplTests {
    
        // 1) Implementation of AccountRepository interface is created:
        private AccountRepository accountRepository = createMock(AccountRepository.class);
    
        private AuthenticatorImpl authenticator = new AuthenticatorImpl(accountRepository);
    
        @Test 
        public void validUserWithCorrectPassword() {
    
            // 2) RECORDING: What behavior to expect?
            expect(accountRepository.getAccount(“lisa”)).andReturn(new Account(“lisa”, “secret”));
    
            // Recording Playback (???)
            replay(accountRepository);
    
            // 3) Excercise the scenario:
            boolean res = authenticator.authenticate(“lisa”, “secret”);
            assertTrue(res);
    
            // 4) Verify mock expectations were met
            verify(accountRepository);
        }
    }
    

    好的,有些东西对我来说非常清楚,但还有其他一些我无法理解的东西。

    会发生什么?

    在我看来:

    1. 创建了一个由 AccountRepository 接口表示的依赖关系的运行时模拟实现,该接口是将 AuthenticatorImpl 类作为单元进行测试所必需的。

    2. 我的模拟记录了对如何用于特定场景的期望,在前面的示例中,期望是:1) METHOD CALLED: getAccount(“Lisa”)和已调用方法的返回值:通过“Lisa”和“secret”作为构造函数参数创建的新Account对象

    3. 好的,直到现在我觉得它已经在dinamically创建了一个特定的模拟对象和帐户对象(带有设置值)我希望检索它来调用 getAccount(“ Lisa“)这个对象的方法。是不是?

      现在我有了第一个疑问:以下几行究竟是什么?

      replay(accountRepository);
      

      是否只调用Mock对象?

      1. 然后,我对 AuthenticatorImpl 类的 authenticate()方法执行测试。如果 assertTrue(res); 返回“绿色条”,则测试通过。

      2. 验证线路符合模拟期望:

        验证(accountRepository);

      3. 好的......但是这条线到底是做什么的?因为我认为如果单位测试通过(“绿色条”)或未通过(“红色条”)是前一个断言的结果,为什么测试结束了这个验证()方法并将它传递给模拟对象?这种方法是什么?

        TNX

2 个答案:

答案 0 :(得分:2)

使用EasyMock通常会执行以下操作:首先创建模拟。然后记录预期的行为,如果需要返回/例外/ ...然后你将你的模拟放入重放模式。即你告诉EasyMock你已经完成了录制,现在如果你在你的模拟上调用一个方法,你实际上想要记录的行为。然后,您将调用业务逻辑进行测试。之后,执行断言并确保业务逻辑通过调用verify正确执行预期的行为(调用mocks方法)。

答案 1 :(得分:1)

  

现在我有了第一个疑问:以下几行究竟是什么?

replay(accountRepository);

模拟对象的生命中有两个阶段:

  1. 设定期望
  2. 被行使
  3. replay(mockObject)调用将模拟从一个阶段移动到另一个阶段。

      

    因为我认为如果通过单元测试会说什么(“绿条”)   或不通过(“红色条”)是前一个断言的结果,为什么   测试结束时调用这个verify()方法并将其传递给mocked   宾语?这种方法是什么?

    这是错误的。仅 assertTrue(res)不足以判断测试是否成功。

    使用您的示例,假设验证程序在调用authenticator.authenticate(“lisa”, “secret”)时返回预期结果,但没有在内部调用存储库。测试应该通过吗?不是,这就是您使用replay(accountRepository)检查的内容。