[英]How to replace a bean with a testing mock in Spring Boot for integration testing
I have a spring app and integration tests for this app.我有一个 spring 应用程序和此应用程序的集成测试。 I would like to replace a bean with a mock bean.我想用模拟 bean 替换 bean。
My real bean looks like this我真正的豆子是这样的
@Service
public class MyService {
}
and for testing I would like it to be replaced并且为了测试我希望它被替换
@Service
public class TestMyService {
}
All I can think of is to use profiles for different services.我能想到的就是为不同的服务使用配置文件。 For example:例如:
@Service
@Profile("!test")
public class MyService implements IMyService {
}
@Service
@Profile("test")
public class TestMyService implements IMyService {
}
And then I autowire the bean like this然后我像这样自动装配bean
@Autowired
private IMyService myService;
Is there a better way?有没有更好的办法?
My personal preference is to avoid loading the compete context for testing. 我个人的喜好是避免加载竞争环境进行测试。 Therefore I like my test to focus on a subset of beans. 因此,我希望我的测试专注于豆子集。 It usually means I outline beans which I use in tests: 这通常意味着我概述了在测试中使用的bean:
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = {TestMyService.class, OtherClassNeededForTesting.class}
)
public class DelaysProviderTest {
}
If more configuration is needed I tend to prepare a separate configuration class for tests: 如果需要更多配置,我倾向于准备单独的配置类以进行测试:
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = MyTest.Cfg.class
)
public class MyTest {
@Import({
// .. some classes to import including TestMyService.class
})
@Configuration
public static class Cfg {
}
}
When even more configuration is needed (or mocking), I use the test configuration for providing appropriate mocks 当需要更多配置(或模拟)时,我使用测试配置来提供适当的模拟
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = MyTest.Cfg.class
)
public class MyTest {
@Import({
// .. some classes to import
})
@Configuration
public static class Cfg {
@Bean
public IMyService service() {
IMyService mock = Mockito.mock(IMyService.class);
when(mock.someMethod()).thenReturn("some data");
return mock;
}
}
}
You can name your beans, in your case something like 您可以命名您的豆子,例如
@Service("testService")
public class TestMyService implements IMyService {
}
and in your test class, you can explicitely ask for test service using @Qualifier
, like 在您的测试课程中,您可以使用@Qualifier
明确要求测试服务,例如
@Qualifier("testService")
@Autowired
private IMyService myService;
Spring Boot has @MockBean
and @SpyBean
annotations exactly for this purpose: Spring Boot正是为此目的提供了@MockBean
和@SpyBean
批注:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-mocking-beans
Declaration is simple: 声明很简单:
@MockBean
private MyService myService;
Spring Boot will inject Mockito mock there instead of the actual bean. Spring Boot将在此处注入Mockito模拟,而不是实际的bean。
For Spring Boot, @MockBean
(and @SpyBean
) are likely your best bets as noted in Grzegorz Poznachowski's answer.对于 Spring 引导, @MockBean
(和@SpyBean
)可能是您在 Grzegorz Poznachowski 的回答中指出的最佳选择。
For non Spring Boot Applications , an alternative is to use @Primary
to annotate the mock/stub @Bean
/ @Service
definition.对于非 Spring 引导应用程序,另一种方法是使用@Primary
来注释模拟/存根@Bean
/ @Service
定义。 That annotation "indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency."该注释“表明当多个候选者有资格自动装配单值依赖项时,应优先考虑 bean”。 As such, your mock will be used over the "real" one when wiring other Beans/Configurations.因此,在连接其他 Bean/配置时,您的模拟将用于“真实”模拟。
@SpringJUnitWebConfig(MyAppConfig.class)
public class MyUintTest
{
@Autowired
private ServiceInterface serviceMock;
@Autowired
private SomeClass someClassMock;
@Test
public void myTest()
{
when(someClassMock.getProperty()).thenReturn(properties.get());
// . . .
}
@Service
@Primary
static class TestService implements ServiceInterface
{
// . . .
}
@Configuration
static class Config
{
@Bean
@Primary
public SomeClass someClassBean()
{
return Mockito.mock(SomeClass.class);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.