23

I have a spring boot application with main class like below:

@SpringBootApplication
public class Application {

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

Now I want to test my services and created a base test class:

@SpringApplicationConfiguration(Application.class)
public abstract class TestBase {
}

When I run my test I get exception:

Caused by: java.lang.IllegalArgumentException: Can not load an ApplicationContext with a NULL 'contextLoader'. Consider annotating your test class with @ContextConfiguration.
    at org.springframework.util.Assert.notNull(Assert.java:115)
    at org.springframework.test.context.TestContext.loadApplicationContext(TestContext.java:117)
    at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:148)

Then I change my base test class using ContextConfiguration

@ContextConfiguration(classes = Application.class)
public abstract class TestBase {
}

This time I get DataSource initialization error. I am wondering why it is failing in first case and why in second case it does not load my application.properties where I have configured datasource.

Thank you!

approxiblue
  • 6,982
  • 16
  • 51
  • 59
sansari
  • 558
  • 1
  • 7
  • 17
  • Please include the declaration of the failing test class in addition to the `TestBase` class. – Sam Brannen Jul 22 '16 at 15:02
  • thank you, I managed to resolve this. It was a bad configuration. – sansari Jul 23 '16 at 15:53
  • Could you share your solution? – Fiftoine Sep 22 '16 at 07:06
  • @Fiftoine Hey, I did not change anything in my TestBase class, it was some dependency issues. I just used @SpringApplicationConfiguration(Application.class) on my TestBase to load configurations from Application. What is your problem if I could help you? – sansari Sep 22 '16 at 20:42

4 Answers4

16

Something like that:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest{

   @Autowired
   Foo foo; //whatever you are testing

   @Test
   public void FooTest() throws Exception{
     Foo f = foo.getFooById("22");
     assertEquals("9B", f.getCode); 
   }
 //TODO look into MockMVC for testing services
}
Imran
  • 5,542
  • 3
  • 23
  • 46
Mike3355
  • 11,305
  • 24
  • 96
  • 184
8

Example for Testing with

  • Spring Boot
  • Spring Boot Test Configuration
  • JUnit 5
  • FreeMarker

You will not find all this so simple as below :) Took long time to find out .

Configuration :

@TestConfiguration
@PropertySource(value = "classpath:test.properties", encoding = "UTF-8")
public class GlobalConfig {

    @Bean(name = "JsonMapper")
    public JsonMapper jsonMapper() {

        return new JsonMapper();
    }

    @Bean(name = "ObjectMapper")
    public ObjectMapper objectMapper() {

        return new ObjectMapper();
    }

    @Bean(name = "Mapper")
    public Mapper dozer() {

        return new DozerBeanMapper();
    }

    @Bean(name = "Validator")
    public Validator validator() {

        return new DefaultValidatorAdapter();
    }

}

Actual Test File:

import freemarker.template.Configuration;
import global.GlobalConfig;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;


@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = {GlobalConfig.class, MessagePersistManager.class, TemplateManager.class, FileOperationsManager.class, Configuration.class})
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MessagePersistManagerTest {

    @Autowired
    private MessagePersistManager messagePersistManager;

    @Autowired
    private TemplateManager templateManager;

    @Autowired
    private FileOperationsManager fileOperationsManager;

    @Autowired
    private Configuration freemarkerConfiguration;


    @Value("${channel.outbound.ftp.local.directory}")
    private String sepaFilesBasePath;

    @BeforeAll
    private void init() throws Exception {

        System.out.println("Creating Base Dir=" + sepaFilesBasePath);
        Files.createDirectories(Paths.get(sepaFilesBasePath));

        /* FreeMarker Configuration */
        freemarkerConfiguration.setClassForTemplateLoading(this.getClass(), "/templates/");

    }


    @AfterAll
    private void destroy() throws Exception {

        System.out.println("Deleting Base Dir=" + sepaFilesBasePath);
        FileUtils.deleteDirectory(new File(sepaFilesBasePath));

    }


    @Test
    void persistSepaFile() {
        messagePersistManager.persistSepaFile("sepaWinnings.xml", generateData());
        System.out.println("e");
        assert (true);
    }
Matthias
  • 7,432
  • 6
  • 55
  • 88
GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93
2

You should use initializers.

Please refer the below questions.

spring test not populating database configuration from application.properties

Spring boot, read yml properties via integration test case

Community
  • 1
  • 1
zeagord
  • 2,257
  • 3
  • 17
  • 24
0

I faced the same issue it is because my ServletInitializer was in the different package. Problem resolved after correcting the package structure.