Max
Max

Reputation: 475

Using test application.properties file with CamelSpringTestSupport in Spring Boot

Prerequisites

Problem

I am Using Spring Boot with a configuration class which is also used by EndpointSetup.

@SpringBootApplication
@Import({MyConfiguration.class, EndpointSetup.class})
public class MyFatJarRouter extends FatJarRouter { ... }


@Configuration
@ConfigurationProperties(prefix = "camel.route", ignoreUnknownFields = false)
public class MyConfiguration {
    private List<String> brokerUrl = new ArrayList<>();
    public List<String> getBrokerUrl() {return brokerUrl;}
    public void setBrokerUrl(List<String> brokerUrl) {this.brokerUrl = brokerUrl;}

}

In production properties will be read from conf/application.properties by default.

I want to test my routes via CamelSpringTestSupport

So I have tried following:

I have placed a application.properties under test/resources/config/application.properties (--> in classpath of test)

then wrote following:

public class MyJmsTest extends CamelSpringTestSupport {

    @Override
    protected AbstractApplicationContext createApplicationContext() {
        return new AnnotationConfigApplicationContext(MyFatJarRouter.class);
    }

    @Test
    public void myTest() throws Exception {
        ...
    }
}

In the example above the configuration is not read from the application.properties placed in test folder.

How can I read a test specific config file in my CamelSpringTestSupport Unit-Test?

Upvotes: 1

Views: 5019

Answers (3)

Biplob Biswas
Biplob Biswas

Reputation: 1881

I solved this issue, with a lot of annotation which I found here, and now the test properties are correctly injected:

@RunWith(CamelSpringBootRunner.class)
@SpringBootTest
@ActiveProfiles("test")
@EnableAutoConfiguration
@ComponentScan
@ContextConfiguration()
public class MessageDeliveryTest{
}

Also, the test properties file needs to be named application-{env}.properties, where "env" is the profile used here. For eg. for test the properties file should be application-test.properties

Upvotes: 0

Abhijit Sarkar
Abhijit Sarkar

Reputation: 24568

I may be little late in answering, but there is a better way than hacking endpoints. The following solution uses toD introduced in Camel 2.16. I wrote a custom component "github" (there's an official one as well), and the following is how I test it. Note that I'm not using a single Camel proprietary annotation. To inject properties, I can either use the properties attribute in @SpringBootTest, or any of the other standard techniques available in Spring Boot.

Note that I'm using $simple{...} to avoid clash with Spring property resolution.

<rant>

And yes, Camel documentation sucks! They write it like release notes, with a section dedicated to each release, and don't seem to update the doc to keep up with the latest versions (the following technique is not documented). Imagine going to a restaurant and asking for the special, only to be told by the server about the special for the day before, and the week before, and so on. How about versioning the doc instead?

</rant>

@RunWith(CamelSpringBootRunner.class)
@SpringBootTest
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
public class GitHubRouteTest {
    @Autowired
    private CamelContext camelContext;

    @Autowired
    private ProducerTemplate template;

    @Autowired
    private GitHubClient gitHubClient;

    @Test
    public void testGitHubClientInvoked() throws InterruptedException {
        template.sendBodyAndHeader("direct:start", "whatever",
                "endpoint", "commits/test/test?username=test&password=test");

        verify(gitHubClient).getCommitsForARepo(eq("test"), eq("master"), eq("test"), eq(20));
    }

    @SpringBootApplication
    public static class TestApplication {
        public static void main(String[] args) {
            new SpringApplicationBuilder()
                    .sources(TestApplication.class)
                    .web(false)
                    .run(args);
        }

        @Bean
        public RouteBuilder testRoute() {
            return new RouteBuilder() {
                @Override
                public void configure() throws Exception {
                    from("direct:start")
                            .toD("github:$simple{in.header.endpoint}");
                }
            };
        }

        @Bean
        public GitHubClient mockGitHubClient() {
            GitHubClient mock = Mockito.mock(GitHubClient.class);

            return mock;
        }
    }
}

Upvotes: 3

Max
Max

Reputation: 475

I solved it by using standard spring unit-tests like this:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = Application.class)
    @ActiveProfiles("test") // Load applicaton-test.properties in test/resources/config/application-test.properties
    @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) // cleanup spring context because jms broker does not exit properly
    public class MyJmsTest {

            private static final String MOCK_MY_ENDPOINT = "mock:myEndpoint";

            @Autowired
            CamelContext context;

            @Autowired
            ApplicationContext applicationContext;

            @Autowired
            ProducerTemplate producerTemplate;



           @Before
           public void configureMocks() throws Exception {
              context.getRouteDefinition("MyRoute")
             .adviceWith(context, new AdviceWithRouteBuilder() {
                @Override
                public void configure() throws Exception {
                    weaveByToString(".*myEndPointId.*")
                            .replace()
                            .to(MOCK_MY_ENDPOINT);
                }
              });

           final MockEndpoint endpoint = context.getEndpoint(MOCK_MY_ENDPOINT, MockEndpoint.class);
           endpoint.whenAnyExchangeReceived(new Processor() {
               @Override
               public void process(Exchange exchange) throws Exception {

                   InputStream inStream = getClass().getClassLoader().getResourceAsStream("xml/my.xml");
                   String in = context.getTypeConverter().convertTo(String.class, inStream);
                   exchange.getIn().setBody(in);
               }
            });
          }




            @Test
            public void synchronousCallBasic_1() throws Exception {
                    final MyConfiguration MyConfiguration = applicationContext.getBean(MyConfiguration.class);
                    final String myMessageBody =
                            context.getTypeConverter().convertTo(String.class, getClass().getClassLoader()
                                    .getResourceAsStream("xml/0010_example.xml"));

                    final Object myResult = producerTemplate.requestBody(MyConfiguration.getActiveMqSynchronousEndpointUri(), myMessageBody);

                    assertThat(myResult, notNullValue());
                    assertThat((String)myResult, is("<example>1</example>"));
            }
    }

Upvotes: 0

Related Questions