How to write unit test for spring cloud stream function based method?

2.5k views Asked by At

When I try to test a spring cloud stream function based method, it always happens NullPointerException about InputDestination.

I have two questions:

  1. It's hard for me to know how to write UT from the official doc. official test doc
  2. Besides, how to write integration Test if test file has some dependencies. It seems create a new context and always has NoSuchBeanDefination error.

I have tried as flow, but the context can not find some dependency beans.

@Test
public void sampleTest() {
    try (ConfigurableApplicationContext context = new SpringApplicationBuilder(
                TestChannelBinderConfiguration.getCompleteConfiguration(
                        MyTestConfiguration.class))
                .run("--spring.cloud.function.definition=uppercase")) {
        InputDestination source = context.getBean(InputDestination.class);
        OutputDestination target = context.getBean(OutputDestination.class);
        source.send(new GenericMessage<byte[]>("hello".getBytes()));
        assertThat(target.receive().getPayload()).isEqualTo("HELLO".getBytes());
    }
}

So I just want to write UT, but still have NPE.

Here is my code.


    @Bean
    public Function<Message<List<DemoBean>>, Message<DemoBean>> findFirstBean( ){
        return message -> {
            List<DemoBean> demoBeans =  message.getPayload();
            return MessageBuilder.withPayload(demoBeans.get( 0 )).build();
        };
    }

Here is my test.


    @SpringBootTest
    @ActiveProfiles(profiles = "local")
    @Import({ TestChannelBinderConfiguration.class})
    class FunctionDemoTest {

    @Autowired
    private InputDestination inputDestination;
    @Autowired
    private OutputDestination outputDestination;
    private FunctionDemo functionDemo;
    // some dependency need to mock
    private DemoService demoService;


    @BeforeEach
    void setUp() {
        demoService = Mockito.mock( DemoService.class );
        functionDemo = new FunctionDemo( demoService);
    }


    @Test
    public void findFirstBeanTest() {
        DemoBean demoBean = new DemoBean();
        demoBean.setName("Howard");
        demoBean.setAge( 1 );
        DemoBean demoBean1 = new DemoBean();
        demoBean1.setName("Frank");
        demoBean1.setAge( 2 );
        List<DemoBean> demoBeanList = new ArrayList<>();
        demoBeanList.add( demoBean );
        demoBeanList.add( demoBean1 );

        Message<List<DemoBean>> inputMessage = MessageBuilder.withPayload(demoBeanList).build();
        inputDestination.send(inputMessage,"findFirstBean-in-0");
        
        Assertions.assertNotNull(  outputDestination.receive( 10000, "findFirstBean-out-0") );

    }


    }

Here is error:

java.lang.NullPointerException: while trying to invoke the method org.springframework.messaging.SubscribableChannel.send(org.springframework.messaging.Message) of a null object returned from org.springframework.cloud.stream.binder.test.InputDestination.getChannelByName(java.lang.String)

    at org.springframework.cloud.stream.binder.test.InputDestination.send(InputDestination.java:89)
    at com.successfactors.caf.listener.FunctionDemoTest.raePdrResultProcessor(FunctionDemoTest.java:82)
1

There are 1 answers

5
Frank On

Well, I know the root cause of NPE.

Message<byte[]> receive(long timeout, String bindingName)

It seems should be destinationName instead of bindingName in source code.

Any other answers would be appreciated.