Mockito:与此模拟游戏零互动

Are*_*efe 1 java junit mockito

我有一堂课要测试。

@Configuration
@Import(EmailageConfiguration.class)
public class EmailageServiceConfiguration {

    private static final String EMAILAGE_ACCOUNT_ID_CONFIG_KEY = "emailage.key";
    private static final String EMAILAGE_API_KEY_CONFIG_KEY = "emailage.secret";

    @Bean
    public EmailageConfigHolder emailageConfigHolder(Environment env) {

        final EmailageConfigHolder holder = new EmailageConfigHolder();

        holder.setApiKey(env.getRequiredProperty(EMAILAGE_API_KEY_CONFIG_KEY));
        holder.setAccountId(env.getRequiredProperty(EMAILAGE_ACCOUNT_ID_CONFIG_KEY));

        return holder;
    }

}
Run Code Online (Sandbox Code Playgroud)

提供了我的测试课程,

@RunWith(MockitoJUnitRunner.class)
public class EmailageServiceConfigurationTest {

    @InjectMocks
    private EmailageServiceConfiguration configuration;

    @Mock
    private Environment environment;

    @Mock
    private EmailageConfigHolder holder;

    @Test
    public void testEmailageConfigHolder() {

        when(environment.getRequiredProperty(anyString())).thenReturn(anyString());

        configuration.emailageConfigHolder(environment);

        verify(holder, times(1)).setApiKey(anyString());
        verify(holder, times(1)).setAccountId(anyString());
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到下面提供的错误堆栈,

想要但不被调用:holder.setApiKey(); ->在com.ratepay.ella.service.config.EmailageServiceConfigurationTest.testEmailageConfigHolder(EmailageServiceConfigurationTest.java:48)上,实际上,此模拟的交互为零。想要但不被调用:holder.setApiKey(); ->在com.ratepay.ella.service.config.EmailageServiceConfigurationTest.testEmailageConfigHolder(EmailageServiceConfigurationTest.java:48)上,实际上,此模拟的交互为零。在com.ratepay.ella.service.config.EmailageServiceConfigurationTest.testEmailageConfigHolder(EmailageServiceConfigurationTest.java:48)在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) .reflect.DelegatingMethodAccessorImpl。

如何更正测试?

Gho*_*ica 5

这里:

final EmailageConfigHolder holder = new EmailageConfigHolder();
Run Code Online (Sandbox Code Playgroud)

Mockito无法将模拟注入局部变量。该文档对此非常明确:

Mockito将尝试仅通过构造函数注入,setter注入或属性注入按顺序注入模拟,如下所述。

基本上,通过new()在方法体内使用,您编写了很难测试的代码。因为使用Mockito,您有零个选项来控制new()将在该方法主体中返回的内容。

解决方法:

  • 将“ holder”设置为类的一个字段,然后通过该注释或通过接受Holder实例的构造函数进行注入
  • 将实例作为参数传递给方法

或者假设您可以在单元测试设置的生产代码中实际创建一个新的Holder对象,并且在返回该对象时,只需对返回的对象的属性进行断言。从这个角度来看,您根本不需要在这里使用模拟。只需验证从该调用返回的对象是否具有预期的属性即可!

或者,(不建议)您可以使用PowerMock(ito)或JMockit,以控制对的调用new()。但是如前所述:最好重新编写代码以使其易于测试

顺便说一句:真正的答案是您退后一步,阅读有关Mockito的出色教程。您无法通过反复试验来学习如何使用这样的框架。通过漂亮的小示例学习如何正确地做到这一点,然后,当您了解如何连接点之后,将其应用于您自己的代码!