模拟弹簧组件

问题描述 投票:0回答:2

我正在使用 Mockito 来模拟 spring beans。

当我模拟接口时它工作得很好。

在我们的应用程序中,很少有@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 实现。

mocking mockito powermock spring-test powermockito
2个回答
6
投票

问题

您经常混合使用框架和注释。 Spring 使用

@Autowired
。 Mockito 使用
@Mock
@InjectMocks
。您还可以使用多种方法在测试中配置应用程序上下文 -
@Configuration
@ContextConfiguration(locations = { ... })
- 但这种方式不起作用。有关所有详细信息,请参阅混合 XML、Groovy 脚本和带注释的类

问题是您是否想使用模拟编写单元测试,或者是否想不使用模拟而是使用 Spring 上下文编写集成测试?

单元测试

如果你想模拟

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

@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 { ... }

0
投票
public EmailSender emailSender;
public EmployeeImpl employeeImpl;   
    
@BeforeEach
    public void setUp() {
        emailSender= Mockito.mock(emailSender.class);
    
        // Manually create an instance and set mocks
       employeeImpl= new EmployeeImpl (emailSender);
    }
© www.soinside.com 2019 - 2024. All rights reserved.