0

I trying to test the camel output as Object but which fails to get exchange object.This is where it fails Customer resultCustomer = processActs.getExchanges().get(0).getIn().getBody(Customer.class). Please help me to solve this.I referred this Right way to test my object in Camel

Customer POJO:

public class Customer {
    private String firstName;
    private String lastName;
   // getters and setters
    @Override
    public String toString(){
        return firstName +":::" + lastName;
    }
}

Test Route:

public class FileTest4 extends CamelTestSupport {

    @EndpointInject(uri = "direct:teststart")
    private Endpoint start;

    @EndpointInject(uri = "mock:direct:processActs")
    private MockEndpoint processActs;

    @EndpointInject(uri = "mock:direct:write2File")
    private MockEndpoint write2File;

    @EndpointInject(uri = "mock:end")
    private MockEndpoint mockEndResult;

    @Override
    public boolean isUseAdviceWith() {
        return true;
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            @Override
            public void configure() throws Exception {
                from("file:/var/file.log&noop=true").routeId("MY_ROUTE").to("direct:processActs");

                from("direct:processActs").process(exchange -> {
                    List<Customer> customers = new ArrayList<>();
                    customers.add(new Customer("F1", "L1"));
                    customers.add(new Customer("F2", "L2"));
                    customers.add(new Customer("F3", "L3"));
                    exchange.getOut().setBody(customers);
                }).to("direct:write2File");

                from("direct:write2File").split(simple("${body}")).log("Content: ${body}");
            }
        };
    }

    @Override
    protected void doPostSetup() throws Exception {
        context.getRouteDefinition("MY_ROUTE").adviceWith(context, new AdviceWithRouteBuilder() {
            @Override
            public void configure() throws Exception {
                replaceFromWith("direct:teststart");
                weaveAddLast().to("mock:end");
            }
        });
        context.start();
    }

    @Test
    public void testUnmarshal() throws Exception {
        mockEndResult.expectedMessageCount(1);

    // ArrayIndex Exception here exchanges list is empty
        Customer resultCustomer = processActs.getExchanges().get(0).getIn().getBody(Customer.class); 
        assertEquals(resultCustomer.toString(),"F1:::L1"); 

        write2File.expectedBodiesReceived("F1:::L1", "F3:::L3", "F2:::L2");
        template.sendBody("direct:teststart", new File("src/test/resources/test.txt"));
        mockEndResult.assertIsSatisfied();

    }

}
sunleo
  • 10,589
  • 35
  • 116
  • 196
  • sendtBody is called after you are doing the assert. The route is not triggered till the body is sent – Nelson Christos Feb 16 '18 at 08:54
  • @NelsonChristos Thanks for reply, but same exception. – sunleo Feb 16 '18 at 12:43
  • You have to assert the mock before you get the exchanges. As those exchanges are the actual exchange that arrived at the mock. So its expectations has to be meet first, which says 1 message should arrive.https://stackoverflow.com/questions/8579358/testing-camel-with-mockendpoints – Nelson Christos Feb 16 '18 at 13:03
  • List> list = (List>) mockEndResult.getExchanges().get(0).getIn().getBody(); – Nelson Christos Feb 16 '18 at 13:11
  • No that is not working, mockend will have just string not POJO right? – sunleo Feb 16 '18 at 13:22
  • It works for me. I might have change the log or deleted it.. But in essence what I was saying was you would get a list of lists – Nelson Christos Feb 16 '18 at 13:35

1 Answers1

1

It looks like you're inspecting the mock endpoint before you've actually sent any exchanges. Try moving the check to the end of the test, e.g.:

@Test
public void testUnmarshal() throws Exception {
    mockEndResult.expectedMessageCount(1);

    write2File.expectedBodiesReceived("F1:::L1", "F3:::L3", "F2:::L2");
    template.sendBody("direct:teststart", new File("src/test/resources/test.txt"));
    mockEndResult.assertIsSatisfied();

    Customer resultCustomer = processActs.getExchanges().get(0).getIn().getBody(Customer.class); 
    assertEquals(resultCustomer.toString(),"F1:::L1"); 
}

UPDATE

On closer inspection, I think you've got your mocks muddled up. Judging by the assertions you want to check that three customers are written out. However your mocks aren't set up for this.

mock:end is added to the end of MY_ROUTE but that will only ever see the entire customer list returned by the processor in direct:processActs

Also the mocks you declare with @EndpointInject don't get involved in the route because you don't actually mock the real endpoints. You can remove all of them apart from mockEndResult.

The following test does pass.

@Test
public void testUnmarshal() throws Exception {
    mockEndResult.expectedMessageCount(1);

    template.sendBody("direct:teststart", new File("src/test/resources/test.txt"));

    mockEndResult.assertIsSatisfied();

    @SuppressWarnings("unchecked")
    List<Customer> customers = mockEndResult.getExchanges().get(0).getIn().getBody(List.class);
    assertEquals(customers.get(0).toString(), "F1:::L1");
    assertEquals(customers.get(1).toString(), "F2:::L2");
    assertEquals(customers.get(2).toString(), "F3:::L3");
}

That might not be what you want to test, though. Instead you could weave the mock endpoint in to the splitter, then you'd be able to assert individual customers.

@Override
protected void doPostSetup() throws Exception {
    context.getRouteDefinition("MY_ROUTE").adviceWith(context, new AdviceWithRouteBuilder() {
        @Override
        public void configure() throws Exception {
            replaceFromWith("direct:teststart");
        }
    });
    // give direct:write2File the id 'splitter' to be able to advice it
    context.getRouteDefinition("splitter").adviceWith(context, new AdviceWithRouteBuilder() {
        @Override
        public void configure() throws Exception {
            weaveByType(LogDefinition.class).after().to("mock:end");
        }
    });
    context.start();
}

@Test
public void testUnmarshal() throws Exception {
    mockEndResult.expectedMessageCount(3);
    mockEndResult.expectedBodiesReceived("F1:::L1", "F2:::L2", "F3:::L3");

    template.sendBody("direct:teststart", new File("src/test/resources/test.txt"));

    mockEndResult.assertIsSatisfied();
}
batwad
  • 3,588
  • 1
  • 24
  • 38