Java 使用模拟对象的Spring单元测试到底是如何工作的?

Java 使用模拟对象的Spring单元测试到底是如何工作的?,java,spring,junit,mocking,easymock,Java,Spring,Junit,Mocking,Easymock,我正在学习Spring Core认证,我对JUnit测试中使用mock有一些疑问 我知道,与存根不同,存根中我必须实现一个接口来创建一个伪对象(我的存根),使用mock,我使用一个模拟框架(asEasyMock),为我生成一个在测试中使用的模拟对象 因此,使用模拟进行测试的步骤如下: 使用模拟库生成一个模拟对象,动态实现依赖接口 记录模拟,并期望如何将其用于场景:将调用什么方法和返回什么值 演练场景 验证是否满足模拟预期 例如,我可以使用以下测试类: import static org.easy

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

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

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

  • 使用模拟库生成一个模拟对象,动态实现依赖接口

  • 记录模拟,并期望如何将其用于场景:将调用什么方法返回什么值

  • 演练场景

  • 验证是否满足模拟预期

  • 例如,我可以使用以下测试类:

    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);
        }
    }
    
    好的,有些事情我很清楚,但还有一些事情我不明白

    会发生什么

    在我看来:

  • 它是由AccountRepository接口表示的依赖项的运行时模拟实现创建的,该接口需要将AuthenticatorImpl类作为单元进行测试

  • 我的mock被记录下来,期望它将如何用于特定场景,在前面的示例中,期望是:1)调用的方法:getAccount(“Lisa”)和被调用方法的返回值:通过“Lisa”和“secret”作为构造函数参数创建的新Account对象

  • 好的,到现在为止,在我看来,它已经友好地创建了一个特定的mock对象和Account对象(带有设置的值),我希望通过调用该对象上的getAccount(“Lisa”)方法来检索该对象。是这样吗

    现在我有了第一个疑问:下面这句话到底是什么意思

    replay(accountRepository);
    
    调用是否仅用于使模拟对象可用

  • 然后我对AuthenticatorImpl类的authenticate()方法的执行测试。如果资产为真(res)返回一个“绿色条”,测试通过

  • 验证生产线是否满足模拟预期:

    验证(accountRepository)

  • 好的……但这条线到底是干什么的?因为我认为如果单元测试通过(“绿色条”)或未通过(“红色条”)是前面断言的结果,那么为什么测试结束时调用这个verify()方法并将模拟对象传递给它?你认为这个方法怎么样


    Tnx

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

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

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

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

    现在我有了第一个疑问:下面这句话到底是什么意思

    replay(accountRepository);
    
    模拟对象的生命周期分为两个阶段:

  • 设定期望值
  • 正在行使
  • replay(mockObject)
    调用将模拟从一个阶段移动到另一个阶段

    因为我认为,如果单元测试通过(“绿色条”),该怎么办 或未通过(“红色条”)是前一个断言的结果,为什么 测试端调用这个verify()方法并将模拟的 对象你认为这个方法怎么样

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

    使用您的示例,假设在像authenticator.authenticate(“lisa”、“secret”)一样被调用时,验证器返回预期结果,但不在内部调用存储库。考试应该通过吗?不是,这就是您使用
    重播(accountRepository)
    检查的内容

    现在我有了第一个疑问:下面这句话到底是什么意思

    replay(accountRepository);
    
    模拟人生有两个阶段