0

I'm new into TDD, currently I'm learning a bit about how I can code automated tests to my spring boot APIs.

So, I have an application that recover a bunch of reports from my database.

I tried to use an custom test from a book that I'm reading. But the test doesn't work.

Always that I've tried to run my tests I got a exception:

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:125)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:108)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
    at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:227)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:246)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 1 in XML document from class path resource [application.properties] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:398)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:335)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:187)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:223)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:194)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:258)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadBeanDefinitions(AbstractGenericContextLoader.java:257)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:124)
    at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:107)
    at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:243)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:117)
    ... 25 more
Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
    at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:204)
    at java.xml/com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:178)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:400)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:327)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1471)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:963)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:532)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:243)
    at java.xml/com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
    at org.springframework.beans.factory.xml.DefaultDocumentLoader.loadDocument(DefaultDocumentLoader.java:77)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadDocument(XmlBeanDefinitionReader.java:428)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
    ... 38 more

This is the test that I'm trying to run.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:application.properties")
@ActiveProfiles("local")
public class ReportControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void doesRecoverPercentageOfInfectedPatients() throws Exception {

        MvcResult result = mvc.perform(get("/api/report/infected").contentType(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk()).andReturn();


        assertThat(result.getResponse().getStatus()).equals(status().isOk());
    }

}

Any suggestions or advice about how I can run this test properly or what I'm doing wrong?

For update:

Main class

@SpringBootApplication
public class ReportApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(ReportApiApplication.class, args);
    }
}

My application.properties looks like this:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/zssn?useSSL=false
spring.datasource.username=root
spring.datasource.password=root

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
  • Could you give more info on your project setup? Is it xml or java configuration? Have you seen this question? https://stackoverflow.com/questions/24776669/failed-to-load-applicationcontext-from-unit-test-filenotfound – Christos Karapapas Jun 03 '18 at 14:42
  • @Karapapas In my case I'm just using the application.properties file where I put all data to access my database and configurations to hibernate framework. –  Jun 03 '18 at 15:01
  • Could you paste your properties file? I think the error gives you a pretty good hint about the problem. `Line 1 in XML document from class path resource [application.properties] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.` – Christos Karapapas Jun 03 '18 at 19:30
  • @Karapapas I've added my application.properties at the end of my question. Is there something wrong? –  Jun 03 '18 at 19:45
  • Well the properties file seems fine. Is there any .xml file in your project? Maybe there is something wrong with the format of your xml files. What IDE do you use? – Christos Karapapas Jun 03 '18 at 19:55
  • @Karapapas is there no .xml files. But I think that maybe I found the root of my issue. I'll make a quickly test and than I came back. About my IDE I use spring tool suit, the latest version. –  Jun 03 '18 at 19:59
  • Try to add `@ImportResource("classpath:application.properties")` right after `@SpringBootApplication` on your main class. – Christos Karapapas Jun 03 '18 at 20:14
  • @Karapapas I found the issue. So the problem happened because the version of java that I've been using. I'm using the version 10 for a long time, and never got any kind of problem when I build my APIs. But now when I package my application I've notice that some classes don't have been compiled. So when I checked what classes was, I notice that those specific classes are not compatible with java 10 yet. So I've installed the version 8. The classes has been compiled and also my tests start to work properly. –  Jun 03 '18 at 20:20

2 Answers2

0

You should change ReportControllerTest as below. Need to remove @ContextConfiguration(locations="classpath:application.properties")

Also create application.local.properties under resource directory for your @ActiveProfiles("local")

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(SpringBootTest.WebEnvironment.MOCK)
@AutoConfigureMockMvc
@ActiveProfiles("local")
public class ReportControllerTest {

    @Autowired
    private MockMvc mvc;

    @Test
    public void doesRecoverPercentageOfInfectedPatients() throws Exception {

        MvcResult result = mvc.perform(get("/api/report/infected").contentType(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk()).andReturn();


        assertThat(result.getResponse().getStatus()).equals(status().isOk());
    }

}
Gaurav Srivastav
  • 2,381
  • 1
  • 15
  • 18
0

After some research and helpful talking I've figure out the problem. So, actually I'm using Java 10, JUnit 4 and mockito 2. My API works fine. But I've noticed some classes of hibernate have not compiled properly when I've tried to built the artifact, this happens because an the hibernate have not full support of Java 10 yet.

I've used this as my argument and found that JUnit and Mockito don't have full support to java 10 too. So, all that I've did was change my development environment to Java 8, with that my tests start work properly.

That is the final version of one of my tests. I did some changes based on all advice that I've get on the comments.

@SpringBootTest
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
public class ReportControllerTest {

    @Autowired
    private MockMvc mvc;

    @Autowired
    private WebApplicationContext ctx;

    @Before
    public void setUp() {
        this.mvc = MockMvcBuilders.webAppContextSetup(this.ctx).build();
    }

    @Test
    public void doesRecoverPercentageOfInfectedPatients() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/api/report/infected")
                .accept(MediaType.APPLICATION_JSON))
        .andExpect(status().isOk());
    }

}