6

This is probably quite basic, but I'm new to Spring Boot (and many aspects of Spring in general) and the documentation didn't directly answer this.

The setup

Using latest Spring Boot (1.2.1), I have some integration tests where Spring is loaded up and dependencies nicely autowired (it was delightfully simple to set this up).

Base class for tests:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public abstract class IntegrationTest {

}

The main Application class doesn't have much more than main method with SpringApplication.run() and these annotations:

@ComponentScan
@EnableAutoConfiguration
@EnableScheduling

Example test:

public class UserServiceTest extends IntegrationTest {    
    @Autowired
    UserService userService;

    @Test
    public void testSomething() throws Exception {
        // Use UserService; make assertions
    }    
}

For necessary dependiencies, I just have spring-boot-starter-test:

<!-- Typical Spring Boot test dependencies: Spring Test, JUnit, Hamcrest, Mockito -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

The problem

I created a custom ErrorController along these lines, where I define an @Autowired ErrorAttributes field. See the CustomErrorController source code.

After this, the Spring integration tests stopped working:

java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
    No qualifying bean of type [org.springframework.boot.autoconfigure.web.ErrorAttributes] found for dependency: 
    expected at least 1 bean which qualifies as autowire candidate for this dependency. 
    Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

The question

What is the simplest, cleanest way to get that ErrorAttributes bean injected also in tests?

Should I create separate Application used for tests, with some kind of mocked ErrorAttributes bean, or might there be a simpler way? Am I missing some helper or dependency related to web/controller testing?

3 Answers 3

8

You can annotate a test class with @WebAppConfiguration to instruct Spring's test framework to create a web application context (which is sufficient for autowiring ErrorAttributes) without actually starting the embedded container.

1
  • 1
    Maybe i misuse this annotation, but is use @ WebAppConfiguration with @ IntegrationTest and a still start the embedded container. My workaround was to use @ IntegrationTest({"many other param...","server.port:0"}) and it is OK now
    – pdem
    Commented Sep 2, 2015 at 8:18
7

Annotate your test base class or individual test case classes with @WebIntegrationTest

It's mentioned here:

http://docs.spring.io/spring-boot/docs/1.2.1.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications

6
  • Thanks, this seems to work. (Btw, those who run into IllegalStateException: Tomcat connector in failed state when trying to run tests, it's probably because you have your dev already server running on the same localhost port.)
    – Jonik
    Commented Feb 23, 2015 at 12:18
  • 1
    I didn't mention it because it wasn't specifically asked for in the question, but you can use @WebIntegrationTest(randomPort=true) and then autowire the actual port used with @Value("${local.server.port}") int port; in your test class.
    – ci_
    Commented Feb 23, 2015 at 12:40
  • Ah, thanks! In the end I went with a non-random, non-default port as in the docs: @WebIntegrationTest("server.port:9000")
    – Jonik
    Commented Feb 23, 2015 at 12:56
  • 2
    @Jonik You can also use @WebAppConfiguration on your test class to get a web application context (which is sufficient for autowiring ErrorAttributes) without actually starting the embedded container. Commented Feb 23, 2015 at 15:13
  • 1
    @WebIntegrationTest is deprecated now. See stackoverflow.com/questions/39417530/…
    – shobull
    Commented Dec 12, 2017 at 8:53
2

Following code is working for me Spring boot with annotation

@RunWith(SpringJUnit4ClassRunner.class)

@SpringApplicationConfiguration(classes =Application.class)

@WebIntegrationTest(randomPort=true)

@ContextConfiguration(classes = Application.class)


public class MyRepositoryIntegrationTests  {

    @Autowired
    private IMyRepository myRepository;



       @Test
       public void testSalutationMessage() {
          System.out.println("Inside testSalutationMessage()"+my.findAll());

          //assertEquals(message,message);
       }

}

Not the answer you're looking for? Browse other questions tagged or ask your own question.