【问题标题】:Mock Spring Component模拟弹簧组件
【发布时间】:2017-06-22 07:29:37
【问题描述】:

我正在使用 Mockito 来模拟春豆。

当我模拟一个界面时它工作正常。

在我们的应用程序中,很少有没有实现任何接口的@Component bean。

当我尝试模拟此类组件时,spring 上下文会尝试将属性注入这些组件中。

Mockito 不支持模拟不实现任何接口的 spring 组件吗?

根据要求附上示例

public interface EmployeeInterface {
    public Long saveEmployee(Employee employee);
}

@Component
public class EmployeeImpl implements EmployeeInterface {

    @Autowired
    public EmailSender emailSender

    public Long saveEmployee(Employee employee) {
        ...
    }
}

public interface EmailSender {
    public boolean sendEmail(Email email);
}

@Component
public class EmailSenderImpl implements EmailSender {

    @Autowired
    MailServerInfo  MailServerInfo;

    public boolean sendEmail(Email email) {
        ...
    }
}

public interface MailServerInfo {
    public String getMailServerDetails();
}

@Component
public class MailServerInfoImpl {

    public String getMailServerDetails() {
        ...
    }
}

@Profile("Security-test")
@Configuration
public class SecurityTestMockConfiguration {

    @Bean
    @Primary
    public EmailSender emailSender() {
        return Mockito.mock(EmailSender.class);
    }
}

@ActiveProfiles("Security-test")
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:context-test.xml" })
public class MyTest {

    @Autowired
    EmployeeInterface employeeInterface;

    @Test
    public void testSaveEmployee() {
        employeeInterface.saveEmployee(employee);
    }
}

在上面的示例中,如果我使用 Mockito 模拟 EmailSender,它可以正常工作。

在下面的场景中,EmailSender 是一个没有实现任何接口的 Spring 组件。在以下情况下,我在自动接线时出错。

public interface EmployeeInterface {
    public Long saveEmployee(Employee employee);
}

@Component
public class EmployeeImpl implements EmployeeInterface {

    @Autowired
    public EmailSender emailSender

    public Long saveEmployee(Employee employee) {
        ...
    }
}

@Component
public class EmailSender {

    @Autowired
    MailServerInfo MailServerInfo;

    public boolean sendEmail(Email email) {
        ...
    }
}

public interface MailServerInfo {
    public String getMailServerDetails();
}

@Component
public class MailServerInfoImpl {

    public String getMailServerDetails() {
        ...
    }
}

@Profile("Security-test")
@Configuration
public class SecurityTestMockConfiguration {

    @Bean
    @Primary
    public EmailSender emailSender() {
        return Mockito.mock(EmailSender.class);
    }
}

@ActiveProfiles("Security-test")
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:context-test.xml" })
public class MyTest {

    @Autowired
    EmployeeInterface employeeInterface;

    @Test
    public void testSaveEmployee() {
        employeeInterface.saveEmployee(employee);
    }
}

在第二种情况下,自动装配失败,因为 EmailSender 找不到 MailServerInfo 实现。

【问题讨论】:

  • 请附上你的测试课
  • 附上测试课
  • 请提供 context-test.xml。
  • 您为什么使用 PowerMock 的 PowerMockRunner 和 Mockito 的 mock?你应该坚持使用一个模拟库。
  • 我使用 PowerMockRunner 在我的测试中模拟了一个静态类

标签: mocking mockito powermock spring-test powermockito


【解决方案1】:

问题

您正在混合使用框架和注释。 Spring 使用@Autowired。 Mockito 使用@Mock@InjectMocks。您还可以使用多种方法在测试中配置您的应用程序上下文 - @Configuration@ContextConfiguration(locations = { ... })- 这不是这样工作的。详情请见Mixing XML, Groovy scripts, and annotated classes

问题是您是想使用 mock 编写单元测试,还是想不使用 mock 而使用 Spring 上下文编写集成测试?

单元测试

如果你想模拟 EmailSender,那么使用 Mockito 的 @Mock 注释。然后可以让 Mockito 通过@InjectMocks 注入EmployeeImpl 的依赖项。

@Mock
EmailSender emailSender;

@InjectMocks
EmployeeImpl employee;

你也可以看看这样的教程https://dzone.com/articles/use-mockito-mock-autowired

集成测试

如果您想编写集成测试,请使用任一

@Configuration
public class TestConfiguration { ... }

@ContextConfiguration(classes = { TestConfiguration.class })
public class MyTest { ... }

@ContextConfiguration(locations = { "classpath:context-test.xml" })
public class MyTest { ... }

【讨论】:

  • 感谢您的澄清。那很有用。我想为 spring 上下文编写一个集成测试。在应用程序上下文中会有多个 bean 的嵌套自动装配。通过使用 ActiveProfile 和 @primary 注释,我能够在应用程序上下文中成功地模拟此类 bean。在我的示例中,从 junit 测试类中,我只访问 EmployeeInterface,它在内部依赖于其他 bean。仅当我尝试模拟未实现接口的 Spring Component 时才会出现错误。否则它会起作用。希望我已经把我的场景说清楚了。
  • ContextConfiguration 标签不适用于 MockitoJunitRunner。
猜你喜欢
  • 1970-01-01
  • 2012-06-29
  • 2018-11-22
  • 1970-01-01
  • 2012-03-01
  • 2021-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多