2017-05-17 20 views
1

ファイルの存在を確認している単純なフローを単体テストしようとしています。ユニットテストSpring統合フローDSL

IntegrationFlow

@Bean 
public IntegrationFlow initiateAlarmAck() { 
    return IntegrationFlows.from("processAckAlarmInputChannel") 
      .handle((payload, headers) -> { 
       LOG.info("Received initiate ack alarm request at " + payload); 
       File watermarkFile = getWatermarkFile(); 
       if(watermarkFile.isFile()){ 
        LOG.info("Watermark File exists"); 
        return true; 
       }else{ 
        LOG.info("File does not exists"); 
        return false; 
       } 
      }) 
      .<Boolean, String>route(p -> fileRouterFlow(p)) 
      .get(); 
} 
File getWatermarkFile(){ 
    return new File(eventWatermarkFile); 
} 

@Router 
public String fileRouterFlow(boolean fileExits){ 
    if(fileExits) 
     return "fileFoundChannel"; 
    else 
     return "fileNotFoundChannel"; 
} 

fileNotFoundChannelからのメッセージを選択し、追加の処理を行い、別の統合の流れがあります。私はこの部分をユニットテストしたくない。 fileNotFoundChannelにメッセージを書き込んだ後に、テストをやめて停止するにはどうすればよいですか?我々はMockMessageHandler実装でnowをやっているかを正確にシナリオで事前

答えて

3

@Bean 
public IntegrationFlow fileNotFoundFlow() { 
    return IntegrationFlows.from("fileNotFoundChannel") 
      .handle((payload, headers) -> { 
       LOG.info("File Not Found"); 
       return payload; 
      }) 
      .handle(this::getLatestAlarmEvent) 
      .handle(this::setWaterMarkEventInFile) 
      .channel("fileFoundChannel") 
      .get(); 
} 

ユニットテストクラス

@RunWith(SpringRunner.class) 
@Import(AcknowledgeAlarmEventFlow.class) 
@ContextConfiguration(classes = {AlarmAPIApplication.class}) 
@PropertySource("classpath:application.properties ") 
public class AcknowledgeAlarmEventFlowTest { 


    @Autowired 
    ApplicationContext applicationContext; 

    @Autowired 
    RestTemplate restTemplate; 

    @Autowired 
    @Qualifier("processAckAlarmInputChannel") 
    DirectChannel processAckAlarmInputChannel; 

    @Autowired 
    @Qualifier("fileNotFoundChannel") 
    DirectChannel fileNotFoundChannel; 

    @Autowired 
    @Qualifier("fileFoundChannel") 
    DirectChannel fileFoundChannel; 

    @Mock 
    File mockFile; 

    @Test 
    public void initiateAlarmAck_noFileFound_verifyMessageOnfileNotFoundChannel(){ 


     AcknowledgeAlarmEventFlow.ProcessAcknowledgeAlarmGateway gateway = applicationContext.getBean(AcknowledgeAlarmEventFlow.ProcessAcknowledgeAlarmGateway.class); 
     gateway.initiateAcknowledgeAlarm(); 

     processAckAlarmInputChannel.send(MessageBuilder.withPayload(new Date()).build()); 
     MessageHandler mockMessageHandler = mock(MessageHandler.class); 

     fileNotFoundChannel.subscribe(mockMessageHandler); 
     verify(mockMessageHandler).handleMessage(any()); 
    } 
} 

感謝。

をあなたはstop()にそのfileNotFoundChannelの実.handle((payload, headers))エンドポイントを持っている:あなたはそのfileNotFoundFlowで更なる行動を防ぐために、あざけると右の道を行くが、いくつかの簡単なトリックを逃すよう

が見えます。そうすれば、チャンネルから退会し、メッセージをそれ以上消費することはありません。

return IntegrationFlows.from("fileNotFoundChannel") 
      .handle((payload, headers) -> { 
       LOG.info("File Not Found"); 
       return payload; 
      }, e -> e.id("fileNotFoundEndpoint")) 

を、テストクラス

@Autowired 
@Qualifier("fileNotFoundEndpoint") 
AbstractEndpoint fileNotFoundEndpoint; 
... 

@Test 
public void initiateAlarmAck_noFileFound_verifyMessageOnfileNotFoundChannel(){ 
    this.fileNotFoundEndpoint.stop(); 

    MessageHandler mockMessageHandler = mock(MessageHandler.class); 

    fileNotFoundChannel.subscribe(mockMessageHandler); 


    AcknowledgeAlarmEventFlow.ProcessAcknowledgeAlarmGateway gateway = applicationContext.getBean(AcknowledgeAlarmEventFlow.ProcessAcknowledgeAlarmGateway.class); 
    gateway.initiateAcknowledgeAlarm(); 

    processAckAlarmInputChannel.send(MessageBuilder.withPayload(new Date()).build()); 
    verify(mockMessageHandler).handleMessage(any()); 
} 

ペイで、注意が、私が移動したかからかってくださいとチャネルにメッセージを送信する前にサブスクライブ:この目的のために私がやってお勧めします。

新しいMockIntegrationContext機能では、フレームワークがあなたのためにそのことに気を配ります。しかし、うん...ユニットテストと同じように、モックは相互作用の前に準備する必要があります。

UPDATE

作業サンプルは:

@RunWith(SpringRunner.class) 
@ContextConfiguration 
public class MockMessageHandlerTests { 

    @Autowired 
    private SubscribableChannel fileNotFoundChannel; 

    @Autowired 
    private AbstractEndpoint fileNotFoundEndpoint; 

    @Test 
    @SuppressWarnings("unchecked") 
    public void testMockMessageHandler() { 
     this.fileNotFoundEndpoint.stop(); 

     MessageHandler mockMessageHandler = mock(MessageHandler.class); 

     this.fileNotFoundChannel.subscribe(mockMessageHandler); 

     GenericMessage<String> message = new GenericMessage<>("test"); 
     this.fileNotFoundChannel.send(message); 

     ArgumentCaptor<Message<?>> messageArgumentCaptor = ArgumentCaptor.forClass(Message.class); 

     verify(mockMessageHandler).handleMessage(messageArgumentCaptor.capture()); 

     assertSame(message, messageArgumentCaptor.getValue()); 
    } 

    @Configuration 
    @EnableIntegration 
    public static class Config { 

     @Bean 
     public IntegrationFlow fileNotFoundFlow() { 
      return IntegrationFlows.from("fileNotFoundChannel") 
        .<Object>handle((payload, headers) -> { 
         System.out.println(payload); 
         return payload; 
        }, e -> e.id("fileNotFoundEndpoint")) 
        .channel("fileFoundChannel") 
        .get(); 
     } 

    } 

} 
+0

試験を修正し、 "fileNotFoundChannelは" 直接チャンネルたことに気づきました。私は "fileNotFoundChannel"をSubscribableChannelに変更して、テストケースにmockMessageHandlerをチャンネルに登録できるようにしました。しかし、テストケースの行を検証するための制御は行われません。私はpreSendが 'fileNotFoundChannel'で呼び出されていることが分かります – nkare

+0

私は答えに完全に動作するサンプルを追加しました。モックする前にエンドポイントを停止していることを確認してください。それ以外の場合、 'fileNotFoundChannel'には複数のサブスクライバがあり、最初のものは最初のメッセージをキャッチします。参照:http://docs.spring.io/spring-integration/reference/html/messaging-channels-section.html#channel-implementations-directchannel about LoadBalancingStrategy –

+1

方向性をありがとう。私はエンドポイントを個別にテストするテストクラスでたくさんのテストをしています。彼らは個別にテストしたときにうまく走っていましたが、1つのテストクラスで走っていたときには失敗していました。エンドポイントを停止するすべてのテストでは、テストの最後に開始する必要がありました。また、モックハンドラがチャネルに加入しているときは、テスト終了時にそれを退会する必要がありました。これは、すべてのテストを単一のテストクラスで実行するために必要でした。 – nkare

関連する問題