如何在没有继承的情况下在我的测试中共享@MockBeans 和模拟方法?
How to share @MockBeans and mock methods among my tests without inheritance?
我有一个将被其他集成测试使用的基本测试场景。此场景包括一些用于外部集成的模拟 bean (@MockBean
)。
今天,我在集成测试中遇到了这样的事情class:
@SpringBootTest
@WebAppConfiguration
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@RunWith(SpringRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OrderIT {
以及准备我的集成测试的字段和注释:
private MockMvc mockMvc;
@Autowired
private WebApplicationContext wac;
@Autowired
private ObjectMapper mapper;
@MockBean
private SomeGateway someGateway;
@MockBean
private SomeRabbitMqService someRabbitMqService ;
@MockBean
private AnotherRabbitMqService anotherRabbitMqService;
@MockBean
private SomeIntegrationService someIntegrationService ;
@MockBean
private Clock clock;
@Before
public void setup() {
//some methods mocking each service above, preparing mockMvc, etc
}
此场景对于使用 MockMvc
和创建系统中的主要功能是必要的,我的 Order
。这个 Order
是通过调用 Rest API 中的 POST 方法创建的,将 order
保存在内存数据库中。
即使这样运行良好,我也需要在另一个测试中 复制 这个包含这些 @MockBean
和一些 @Autowired
的代码块,因为 Order
是 基本场景 用于将产品添加到订单、设置要交付的地址等。每个场景都有不同的集成测试,但所有场景都需要 Order
.
那么,如何在我的集成测试中共享 "MockBeans" 和模拟它们的方法?我在测试中使用继承确实糟糕的经历,我真的很想尝试不同的方法。
我最终使用 Spring profiles。
我创建了一个用 @Profile("test")
注释的配置 class 并在那里创建了模拟 bean。喜欢:
@Profile("test")
@Configuration
public class MyMockConfiguration {
@Bean
public SomeService someService() {
SomeService someService = mock(SomeService .class);
// mocked methods and results
return someService ;
}
并且在测试中 class:
@ActiveProfiles("test")
@SpringBootTest
@WebAppConfiguration
@RunWith(SpringRunner.class)
public class MyControllerIT {
如果某些集成测试需要覆盖配置文件上的当前模拟实现,测试只需在 class 上声明 @MockBean
并像往常一样继续模拟。
我还不确定 test
是否是一个好名字,因为对我来说,通过“上下文”模拟配置更有意义。因此,我可以使用 createOrder
并使用不同的配置文件,而不是在配置文件名称上使用通用名称 test
,每个配置文件都有不同的名称和不同的模拟:createOrder
、createOrderWithoutProducts
.
我相信 @ContextConfiguration
是为此目的创建的:https://spring.io/blog/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles
我有一个将被其他集成测试使用的基本测试场景。此场景包括一些用于外部集成的模拟 bean (@MockBean
)。
今天,我在集成测试中遇到了这样的事情class:
@SpringBootTest
@WebAppConfiguration
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_CLASS)
@RunWith(SpringRunner.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OrderIT {
以及准备我的集成测试的字段和注释:
private MockMvc mockMvc;
@Autowired
private WebApplicationContext wac;
@Autowired
private ObjectMapper mapper;
@MockBean
private SomeGateway someGateway;
@MockBean
private SomeRabbitMqService someRabbitMqService ;
@MockBean
private AnotherRabbitMqService anotherRabbitMqService;
@MockBean
private SomeIntegrationService someIntegrationService ;
@MockBean
private Clock clock;
@Before
public void setup() {
//some methods mocking each service above, preparing mockMvc, etc
}
此场景对于使用 MockMvc
和创建系统中的主要功能是必要的,我的 Order
。这个 Order
是通过调用 Rest API 中的 POST 方法创建的,将 order
保存在内存数据库中。
即使这样运行良好,我也需要在另一个测试中 复制 这个包含这些 @MockBean
和一些 @Autowired
的代码块,因为 Order
是 基本场景 用于将产品添加到订单、设置要交付的地址等。每个场景都有不同的集成测试,但所有场景都需要 Order
.
那么,如何在我的集成测试中共享 "MockBeans" 和模拟它们的方法?我在测试中使用继承确实糟糕的经历,我真的很想尝试不同的方法。
我最终使用 Spring profiles。
我创建了一个用 @Profile("test")
注释的配置 class 并在那里创建了模拟 bean。喜欢:
@Profile("test")
@Configuration
public class MyMockConfiguration {
@Bean
public SomeService someService() {
SomeService someService = mock(SomeService .class);
// mocked methods and results
return someService ;
}
并且在测试中 class:
@ActiveProfiles("test")
@SpringBootTest
@WebAppConfiguration
@RunWith(SpringRunner.class)
public class MyControllerIT {
如果某些集成测试需要覆盖配置文件上的当前模拟实现,测试只需在 class 上声明 @MockBean
并像往常一样继续模拟。
我还不确定 test
是否是一个好名字,因为对我来说,通过“上下文”模拟配置更有意义。因此,我可以使用 createOrder
并使用不同的配置文件,而不是在配置文件名称上使用通用名称 test
,每个配置文件都有不同的名称和不同的模拟:createOrder
、createOrderWithoutProducts
.
我相信 @ContextConfiguration
是为此目的创建的:https://spring.io/blog/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles