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?

Community
  • 1
  • 1
Jonik
  • 80,077
  • 70
  • 264
  • 372

3 Answers3

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.

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
  • 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 Sep 02 '15 at 08: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

Jonik
  • 80,077
  • 70
  • 264
  • 372
ci_
  • 8,594
  • 10
  • 39
  • 63
  • 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 Feb 23 '15 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_ Feb 23 '15 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 Feb 23 '15 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. – Andy Wilkinson Feb 23 '15 at 15:13
  • @AndyWilkinson: Thanks, that's actually a better solution for my current needs! I think you should post that as an answer. – Jonik Feb 23 '15 at 16:11
  • 1
    `@WebIntegrationTest` is deprecated now. See https://stackoverflow.com/questions/39417530/what-is-the-proper-annotation-since-springapplicationconfiguration-webintegra – shobull Dec 12 '17 at 08: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);
       }

}
vaquar khan
  • 10,864
  • 5
  • 72
  • 96