Search code examples
junitspring-integrationjunit4

Error Could not open ServletContext resource in jUnit Testing Spring Integration


I am new to Spring Integration and I am trying to test the channel. I have written a below code. but i am getting exception while testing it. Please help me in resolving that.

Spring Integration flow.

<int:channel id="reqGetAllMedChannel" />
<int:channel id="resGetAllMedChannel" />
<int-http:inbound-gateway
    request-channel="reqGetAllMedChannel"
    reply-channel="resGetAllMedChannel" supported-methods="GET"
    path="/getAllMedicines">

    <int-http:request-mapping
        consumes="application/json" produces="application/json" />
</int-http:inbound-gateway>


<int:service-activator
    ref="medicineServiceActivator" method="getAllMedicines"
    input-channel="reqGetAllMedChannel"
    output-channel="resGetAllMedChannel" />

Method which is getting invoked.

public Message<List<Medicine>> getAllMedicines() {
    log.info("GET request for Medicine");
    List<Medicine> medLst = medicineService.getAllMedicines();
    return MessageBuilder.withPayload(medLst).setHeader("http_statusCode", HttpStatus.OK).build();
}

Testing xml configuration

<import resource="classpath:medicineIntegration.xml"/>

<int:bridge input-channel="resGetAllMedChannel" output-channel="testOutput">
</int:bridge>

<int:channel id="testOutput">
<int:queue/>
</int:channel>

jUnit test case.

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(locations= {"classpath*:Integration-Test.xml"})
public class MessageChannelTest {

@Autowired
private MessageChannel inputChannel;

@Autowired
private QueueChannel testChannel;

@Mock
private MedicineService medicineService;

@Test
public void testChannel() {
    List<Medicine> medicines = new ArrayList<Medicine>();
    Medicine medicine1 = new Medicine();
    medicine1.setMedName("Crocine");
    medicine1.setExpDate("01-01-2020");
    Medicine medicine2 = new Medicine();
    medicine2.setMedName("Paracetamole");
    medicine2.setExpDate("02-02-2020");
    medicines.add(medicine1);
    medicines.add(medicine2);
    when(medicineService.getAllMedicines()).thenReturn(medicines);
    inputChannel.send(MessageBuilder.withPayload("").build());
    Message<?> outMsg = testChannel.receive(1000);
    assertThat(medicineService).isEqualTo(outMsg.getPayload());
}
}

Below is the exception i am getting while testing the jUnit code. Please help me and let me know if i am doing something wrong.

java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:190) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:132) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) ~[junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) ~[junit-4.12.jar:4.12]
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190) ~[spring-test-5.1.2.RELEASE.jar:5.1.2.RELEASE]
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463) ~[.cp/:na]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209) ~[.cp/:na]

Solution

  • According the exception your medicineService depends on the MedicineRepository. Since you just have a:

    @Mock
    private MedicineService medicineService;
    

    You don't effect the application context and don't replace your medicineService bean definition.

    If you really want just mock this MedicineService and replace it in the application context, you should consider to use a @MockBean from Spring Boot: https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-mocking-beans

    You also can just @MockBean for that MedicineRepository and your MedicineService will remain the same in the application context.

    I have already suggested you something similar in other your question: JUnit for Spring Integration Activator with return type Message<?>