1

I have a Spring Boot based standalone (non-web) application following this tutorial: https://www.mkyong.com/spring-boot/spring-boot-jdbc-mysql-hikaricp-example/

I skip the hikaricp part as am using mysql directly. The application works fine, able to query, call a RESTful web service... However, I cannot have junit test work, keep getting this error:

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test
    at org.springframework.util.Assert.state(Assert.java:70)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.getOrFindConfigurationClasses(SpringBootTestContextBootstrapper.java:202)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.processMergedContextConfiguration(SpringBootTestContextBootstrapper.java:137)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:409)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:323)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:277)
    at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:112)
    at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:82)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:120)
    at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:105)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:152)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:143)
    at org.springframework.test.context.junit4.SpringRunner.<init>(SpringRunner.java:49)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
    at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
    at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:36)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:275)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:173)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:149)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:128)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)

The related junit test code:

`

@RunWith(SpringRunner.class)
@RestClientTest(ArrivalRestClient.class)
public class ArrivalRestClientTest {
    private static final String MOCK_URL = "http://baseURI/arrival";
    @Autowired
    private ArrivalRestClient clientUnderTest;  
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private MockRestServiceServer mockServer;
    @Autowired
    private RestTemplate restTemplate;
    @Before
    public void setUp() throws Exception {
            mockServer = MockRestServiceServer.createServer(restTemplate);
            clientUnderTest = new ArrivalRestClient(MOCK_URL);
            ReflectionTestUtils.setField(clientUnderTest, "restTemplate", restTemplate);

    }
    @Test
    public void testGetArrivals() throws JsonProcessingException {

        Arrival arrival = new Arrival("JohnTest1", "GLBProduct", 0L);
        String arrivalString = objectMapper.writeValueAsString(arrival);
        this.mockServer.expect(requestTo("/arrival?source=source1&entity=entity1&timestamp=1000")).andRespond(withSuccess(arrivalString, MediaType.APPLICATION_JSON));

        Arrivals actual = clientUnderTest.getArrivals("JohnTest1", "GLBProduct", 0);

        System.out.println("getExpectedtime: " + actual.getNextRunTime());
        System.out.println("getPartitions: " + actual.getPartitions());

        assertEquals((long)2000, actual.getNextRunTime());
        assertEquals(new Long[]{ (long)2,(long)3}, actual.getPartitions());

    }
}`

Even an empty unit test fails. Believe it is related to the fact that it is a Spring Boot standalone application (non-web). I cannot find hints on how to unit it online, thanks for your help!

Edit--- also add my main class code:

@SpringBootApplication
public class DepManagerMain implements CommandLineRunner {

    final static Logger logger = Logger.getLogger(DepManagerMain.class);

    @Autowired
    DataSource dataSource;

    public static void main(String[] args) throws Exception {
        SpringApplication app = new SpringApplication(DepManagerMain.class);
        app.run(args);
    }

    @Override
    public void run(String... args) throws Exception {
        logger.info("DependencyManager starting");
        logger.info("DATASOURCE = " + dataSource);
        ...
    }
}   
rxu
  • 11
  • 4
  • Please read the exception, it's specifically stating exactly what's wrong. `Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test` – Ben M Aug 23 '17 at 15:04
  • 1
    In which package is your Test class? and in which package is your `@SpringBootApplication` class? – larsgrefer Aug 23 '17 at 15:19
  • @SpringBootApplication is in com.foo.pack1, class under test is in com.foo.pack2. Any requirement on this layout? – rxu Aug 25 '17 at 19:02
  • @rxu The `@SpringBootTest`-class must be in the same package or a subpackage of your `@SpringBootApplication` See https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-detecting-config and https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#using-boot-structuring-your-code – larsgrefer Aug 28 '17 at 09:42
  • tried, move @SpringBootApplication class move one level up: com.foo, but same issue. – rxu Aug 30 '17 at 13:45

2 Answers2

0

As far as I know the @RestClientTest annotation provides you with only a limited number of beans.

I don't think RestTemplate is one of those beans so I think the autowiring is failing at this point and hence it is trying to load this from your main @SpringBootConfiguration.

The @RestClientTest annotation does provide you with a RestTemplateBuilder though so you can autowire this in and construct a RestTemplate from that.

Plog
  • 9,164
  • 5
  • 41
  • 66
  • I tried to launch other unit test, even empty one hits this "java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration". I believe it is NOT per unit test, something wrong with the application level setting... – rxu Aug 23 '17 at 15:26
0

You need to annotate your ArrivalRestClientTest by the annotation @SpringBootTest. As the CommandLineRunner is used, CommandLineRunner is facilitated by springboot features such as AutoScan etc. By having @SpringBootTest, the unit test would be able to scan your facilitate the springboot features.

Procrastinator
  • 2,526
  • 30
  • 27
  • 36