Spring Integration Java DSL单元测试——如何模拟Service Activator类或其他组件



我有一个包含如下几个服务激活器方法的类:

@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测试框架的工作原理。

  1. @ContextConfiguration(classes = IntegrationConfig.class)按原样加载配置,不做任何修改,并基于该配置启动应用程序上下文。

  2. 根据第一个条件,您的.handle("testService", "setComplete")使用testService() @Bean而不是@Mock

  3. 只有在测试应用程序上下文启动后,所有这些@Mock@Autowired才开始工作。

换句话说,您的嘲弄不会改变原始IntegrationConfig中的任何内容。

在框架中使用反射来检索特定bean的某些字段以将其替换为mock。但这不是那么容易的方法。

我建议您区分集成和服务配置,并在生产和测试中使用两个不同的类。像这样:

  1. 必须将testService() @BeanIntegrationConfig类移到新的@Configuration类中进行生产。

  2. TestServiceConfig可能看起来像这样:

    @Bean
    public TestService testService() {
        return Mockito.mock(new TestService());
    }
    
  3. 最后你的AppTest应该修改如下:

    @ContextConfiguration(classes = {IntegrationConfig.class, TestServiceConfig.class})
    ....
    @Autowired
    private TestService testrvice;
    
这就是一切,只是因为应用程序上下文和单元测试范围处于不同的级别。

最新更新