我有一个包含一些服务激活器方法的类,如下所示:
@MessageEndpoint
public class TestService {
@ServiceActivator
public void setComplete(Message<String> message){
//do stuff
}
}
在集成流中,其中一个通道调用以下方法之一:
@Bean
public TestService testService() {
return new TestService();
}
@Bean
public IntegrationFlow testFlow() {
return IntegrationFlows.from("testChannel")
.handle("testService", "setComplete")
.handle(logger())
.get();
}
我正在为此流程编写一个单元测试,并使用Mockito来调用服务激活器类:
@ContextConfiguration(classes = IntegrationConfig.class)
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext
public class AppTest {
@Mock
private TheGateway startGateway;
@Mock
private TestService testrvice;
@Autowired
@Qualifier("testChannel")
DirectChannel testChannel;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test()
public void testMessageProducerFlow() throws Exception {
Mockito.doNothing().when(startGateway).execute("test");
startGateway.execute("test");
Mockito.verify(startGateway).execute("test");
TestChannel.send(new GenericMessage<>("test"));
Mockito.verify(testService).setComplete(new GenericMessage<>("test"));
}
}
当我不模拟TestService时,它可以毫无问题地执行流程。
关于如何模拟服务激活器类的任何指导都将有所帮助。
更新:
当我模拟它时(如上面的片段所示),它不会调用模拟对象,而是执行实际的东西,最后一行
Mockito.verify(testService)...
断言从未调用模拟testService。 最佳答案
首先,您会误解Spring Test Framework的工作方式。@ContextConfiguration(classes = IntegrationConfig.class)
无需任何修改即可按原样加载配置,并基于该配置启动应用程序上下文。
根据第一个条件,您的.handle("testService", "setComplete")
使用testService()
@Bean
而不是@Mock
仅在测试applicationContext启动后,所有这些@Mock
和@Autowired
才开始工作。
换句话说,您的嘲笑不会改变原始IntegrationConfig
中的任何内容。
在带有反射的框架中,检索特定bean的某些字段以将其替换为模拟。但这不是那么容易的方法。
我建议您区分“集成”和“服务”配置,并使用两个不同的类进行生产和测试。像这样:testService()
@Bean
必须从IntegrationConfig
移到新的@Configuration
类进行生产。TestServiceConfig
可能看起来像这样:
@Bean
public TestService testService() {
return Mockito.mock(new TestService());
}
最后,您的
AppTest
应该像这样修改:@ContextConfiguration(classes = {IntegrationConfig.class, TestServiceConfig.class})
....
@Autowired
private TestService testrvice;
仅仅是因为应用程序上下文和单元测试范围处于不同的级别。