我有一个包含一些服务激活器方法的类,如下所示:

@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;



仅仅是因为应用程序上下文和单元测试范围处于不同的级别。

10-04 19:26