62

I am using spring boot 1.4.0.RELEASE. I am writing tests for my controller class. I get the following exception.

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.concur.cognos.authentication.service.ServiceControllerITTest': Unsatisfied dependency expressed through field 'restTemplate': No qualifying bean of type [org.springframework.boot.test.web.client.TestRestTemplate] found for dependency [org.springframework.boot.test.web.client.TestRestTemplate]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.boot.test.web.client.TestRestTemplate] found for dependency [org.springframework.boot.test.web.client.TestRestTemplate]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

Here is my test class

public class ServiceControllerITTest extends ApplicationTests {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private MockMvc mvc;

    @Test
    public void exampleTest() throws Exception {
         // test
    }
}

ApplicationTests.java

@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
//@DirtiesContext
public class ApplicationTests {

    @Autowired
    Environment env;

    @Test
    public void contextLoads() {

    }

}
brain storm
  • 30,124
  • 69
  • 225
  • 393

4 Answers4

133

TestRestTemplate is only auto-configured when @SpringBootTest has been configured with a webEnvironment that means it starts the web container and listens for HTTP requests. For example:

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
  • I added. now I get `java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext` – brain storm Aug 29 '16 at 21:49
  • 2
    Are you still trying to autowire `TestRestTemplate` and `MockMvc`? Doing so doesn't make sense. You should use one or the other. – Andy Wilkinson Aug 30 '16 at 05:45
  • It doesn't help either. I commented out `MockMVC` and autowired only `TestRestTemplate`. still I get same error as in above comment – brain storm Aug 30 '16 at 16:27
  • 1
    @AndyWilkinson I'm finding the same behavior (injecting either or both), and the docs explicitly state that the default for `@SpringBootTest` is `MOCK`. – chrylis -cautiouslyoptimistic- Oct 06 '16 at 03:26
  • 1
    @chrylis As I said above, you need to use `RANDOM_PORT` to be able to inject `TestRestTemplate` – Andy Wilkinson Oct 06 '16 at 06:12
  • It doesn't answer the question. wondering why it is most upvoted!! – Avinesh Jul 11 '18 at 07:46
  • 2
    @avinesh The other comments already explain why it doesn't address `MockMvc`. It doesn't make sense to use `TestRestTemplate` and `MockMvc` in the same test. One is for testing a service over HTTP using an embedded servlet container the other is for testing a service without HTTP using a mocked servlet container. – Andy Wilkinson Jul 11 '18 at 08:06
  • @AndyWilkinson yes that's seems reasonable. but if anyone wants both RestTemplate and MockMvc, use '@AutoConfigureMockMvc' over test class to autowire mockMvc. – Avinesh Jul 11 '18 at 09:06
23

If you read the java doc of SpringBootTest annotation, it says that annotation provides below features (not listing all of them here, but only what are relevant to the question.)

  • Provides support for different webEnvironment modes, including the ability to start a fully running web server listening on a defined or random port.
  • Registers a TestRestTemplate and/or WebTestClient bean for use in web tests that are using a fully running web server listening on a defined or random port.

So @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) provides the ability to autowire TestRestTemplate because it starts a fully running web server [as mentioned in @AndyWilkinson' answer as well].

But if you want to autowire MockMvc as well in same TestClass then use @AutoConfigureMockMvc annotation over TestClass.

This is how a Test class may look like:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class SBTest {
    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private MockMvc mvc;

   // tests
}
Avinesh
  • 535
  • 4
  • 10
6

To work with that, don't use a deprecated TestRestTemplate.

Deprecated:

import org.springframework.boot.test.TestRestTemplate;

Correct:

import org.springframework.boot.test.web.client.TestRestTemplate;

Then you can use the @Autowired annotation in your class:

@Autowired
private TestRestTemplate restTemplate;

And don't use:

@Autowired
private MockMvc mvc;

Both together doesn't work.

Meyer
  • 1,662
  • 7
  • 21
  • 20
Jesus Macias
  • 61
  • 1
  • 1
4

According to Spring boot documentation :

You can also auto-configure MockMvc in a non-@WebMvcTest (e.g. SpringBootTest) by annotating it with @AutoConfigureMockMvc.

Aphax
  • 169
  • 3
  • 14
  • This answer helped me for my `@WebMvcTest` (Spring Boot 2.5.5). I just added `@AutoConfigureWebClient` on my test class and then the `UnsatisfiedDependencyException` I was encountering was gone, thank you. – StøcciD Nov 05 '21 at 16:04