spring boot test unable to inject TestRestTemplate and MockMvc
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() {
}
}
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)
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
}
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.
According to Spring boot documentation :
You can also auto-configure MockMvc
in a non-@WebMvcTest
(e.g. SpringBootTest
) by annotating it with @AutoConfigureMockMvc
.