我有一个包含如下几个服务激活器方法的类:
@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();
}
我正在为这个流编写一个单元测试,并使用mockit来生成服务激活器类:
@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时,它会毫无问题地执行流。任何关于如何模拟Service激活器类的指导都会很有帮助。
更新:当我模拟它时(如上面的代码片段所示),它不会调用模拟对象,而是执行实际的内容,最后一行Mockito.verify(testService)...
断言从未调用模拟testService。
首先你误解了Spring测试框架的工作原理。
-
@ContextConfiguration(classes = IntegrationConfig.class)
按原样加载配置,不做任何修改,并基于该配置启动应用程序上下文。 -
根据第一个条件,您的
.handle("testService", "setComplete")
使用testService()
@Bean
而不是@Mock
-
只有在测试应用程序上下文启动后,所有这些
@Mock
和@Autowired
才开始工作。
换句话说,您的嘲弄不会改变原始IntegrationConfig
中的任何内容。
在框架中使用反射来检索特定bean的某些字段以将其替换为mock。但这不是那么容易的方法。
我建议您区分集成和服务配置,并在生产和测试中使用两个不同的类。像这样:
-
必须将
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;