I am testing my web-app with
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApp.class)
//#WebAppConfiguration
#WebIntegrationTest
public class MyTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
}
#Before
public void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext)
.apply(springSecurity())
.build();
}
#Test
public void someTest() throws Exception {
result = mockMvc.perform(get("/user/"));
result
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
...
}
Is it possible to observe how tests run with Filler? Or it sends without network? Is it possible to force MockMvc to use network?
Currently I see nothing in Fiddler.
Setting of
System.getProperties().put("http.proxyHost", "127.0.0.1");
System.getProperties().put("http.proxyPort", "8888");
didn't help.
Related
I have this MvcTest in my application:
#SpringBootTest
#WebMvcTest
public class BarsControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void testBars() throws Exception {
mockMvc.perform(get("/bars")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.*", hasSize(1)));
}
}
but when I run the test mockMvc is null when running the tests.
You shouldn't use #WebMvcTest and #SpringBootTest together.
If you want to test both web layer and other layers Use #AutoConfigureMockMvc and #SpringBootTest together:
#SpringBootTest
#AutoConfigureMockMvc
public class BarsControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void testBars() throws Exception {
mockMvc.perform(get("/bars")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.*", hasSize(1)));
}
}
Or if you only want to test web layer you can use just #WebMvcTest: note the this does not load full spring application context(It only loads web layer)
#WebMvcTest
public class BarsControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void testBars() throws Exception {
mockMvc.perform(get("/bars")
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(status().isOk())
.andExpect(jsonPath("$.*", hasSize(1)));
}
}
This question already has answers here:
Spring Boot - Test for controller fails with 404 code
(10 answers)
Closed 2 years ago.
I've tried a lot but unfortunately without success. I don't understand why I can't reach my controller.I have to run this test via the standalone setup because I don't have a SpringBoot project.
This is my test class:
#RunWith(SpringJUnit4ClassRunner.class)
public class HelpPageControllerTest {
#Mock
private HelpService helpService;
private MockMvc mockMvc;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders
.standaloneSetup(new HelpPageController())
.build();
}
#Test
public void justATest() throws Exception {
ResultActions resultActions = mockMvc.perform(get("/help/manuals?lang=de"));
resultActions.andExpect(status().isOk());
}
}
This is my API that I'm trying to reach:
#GetMapping("/help/manuals")
public ResponseEntity<List<ManualResponseTO>> getManuals(#RequestParam String lang) {
List<ManualResponseTO> manuals;
manuals = this.helpService.getManuals(lang);
return new ResponseEntity<>(manuals, HttpStatus.OK);
}
Running the Test I get this answer:
When i go into the Debug-Mode I can see that the mockMvc is initialized, but I have also set a debug point in my controller, but this I can´t reach.
#RunWith(SpringRunner.class)
#WebMvcTest(HelpPageController.class)
public class HelpPageControllerTest {
#Autowired
private MockMvc mockMvc;
...
}
or
#RunWith(SpringRunner.class)
#WebMvcTest(HelpPageController.class)
public class HelpPageControllerTest {
private MockMvc mockMvc;
#Autowired
private HelpPageController helpPageController;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders
.standaloneSetup(helpPageController)
.build();
}
...
}
dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
I got the solution. I need a test Context Configuration.
testContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
Now I am also mocking my Service. This is the code I need:
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration(locations = "classpath*:testContext.xml")
public class HelpPageControllerTest {
private MockMvc mockMvc;
#Mock
private HelpService helpService;
#InjectMocks
private HelpPageController helpPageController;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders
.standaloneSetup(helpPageController)
.build();
}
#Test
public void justATest() throws Exception {
List<ManualResponseTO> manualResponseTOS = new ArrayList<>();
when(helpService.getManuals("de")).thenReturn(manualResponseTOS);
ResultActions resultActions = mockMvc.perform(get("/manuals?lang=de"));
resultActions.andExpect(status().isOk());
}
}
#AutoConfigureRestDocs and #AutoConfigureMockMvc do not configure MockMvc correctly. Even manually configuring them do not seem to help.
I tried configuring the MockMvc and MockMvcRestDocumentationConfigurer also manually, but it did not help.
This is the current setup:
#RunWith(SpringRunner.class)
#SpringBootTest(properties= "spring.main.allow-bean-definition-overriding=true")
#AutoConfigureRestDocs
#AutoConfigureMockMvc
public class LoginLogoutTest {
#Autowired
private MockMvc mockMvc;
#Test
public void adminCanLoginLogout() throws Exception {
mockMvc.perform(formLogin().user(TestConfig.ADMIN_USERNAME).password(TestConfig.PASSWORD))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername(TestConfig.ADMIN_USERNAME))
.andDo(document("login"));
mockMvc.perform(logout())
.andExpect(status().isOk())
.andExpect(unauthenticated())
.andDo(document("logout"));
}
}
I also tried configuring them with something like this:
#RunWith(SpringRunner.class)
#SpringBootTest(properties= "spring.main.allow-bean-definition-overriding=true")
public class LoginLogoutTest {
#Rule
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");
private MockMvc mockMvc;
#Before
public void setUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration(this.restDocumentation))
.build();
}
#Test
public void adminCanLoginLogout() throws Exception {
mockMvc.perform(formLogin().user(TestConfig.ADMIN_USERNAME).password(TestConfig.PASSWORD))
.andExpect(status().isOk())
.andExpect(authenticated().withUsername(TestConfig.ADMIN_USERNAME))
.andDo(document("login"));
mockMvc.perform(logout())
.andExpect(status().isOk())
.andExpect(unauthenticated())
.andDo(document("logout"));
}
}
I am getting the following error:
java.lang.IllegalStateException: REST Docs configuration not found. Did you forget to apply a MockMvcRestDocumentationConfigurer when building the MockMvc instance?
What am I doing wrong? The error message is not very informative.
Love Spring Testing Even More With Mocking and Unit Test Assistant:
A mocked service replaces multiple dependencies
enter image description here
#Controller
#RequestMapping("/people")
public class PeopleController {
#Autowired
protected PersonService personService;
#GetMapping
public ModelAndView people(Model model) {
for (Person person: personService.getAllPeople()) {
model.addAttribute(person.getName(), person.getAge());
}
return new ModelAndView("people.jsp", model.asMap());
}
}
private MockMvc mockMvc:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class PeopleControllerTest {
#Autowired
PersonService personService;
private MockMvc mockMvc;
#Configuration
static class Config {
// Other beans
#Bean
public PersonService getPersonService() {
return mock(PersonService.class);
}
}
#Test
public void testPeople() throws Exception {
// When
ResultActions actions = mockMvc.perform(get("/people"));
}
}
I get a mistake when I want to run mockMvc
java.lang.NullPointerException
Perform the following steps:
create service mock instead of service original
("PersonServiceMock")
replace service original by service mock
#Autowired
PersonService personService;
#Autowired
PeopleController peopleController;
private MockMvc mockMvc;
#Before
public void setup() {
peopleController = new PeopleController(new personServiceMock());
mvc = MockMvcBuilders.standaloneSetup(peopleController).build();
}
#Configuration
static class Config {
// Other beans
#Bean
public PersonService getPersonService() {
return mock(PersonService.class);
}
}
#Test
public void testPeople() throws Exception {
// When
ResultActions actions = mockMvc.perform(get("/people"));
}
}
That's because you are never initialising mockMvc in your code and the point where you access it results in nullPointerException. You need to initialise it before using it, and since multiple tests in your class could be using it, best place to do it is setup() method annotated with #before. Try below:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class PeopleControllerTest {
#Autowired
PersonService personService;
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
#Configuration
static class Config {
// Other beans
#Bean
public PersonService getPersonService() {
return mock(PersonService.class);
}
}
#Test
public void testPeople() throws Exception {
// When
ResultActions actions = mockMvc.perform(get("/people"));
}
}
from the source code I see that the mockMvc doesn't have any value, thats why it hits "java.lang.NullPointerException" for this line of code :
ResultActions actions = mockMvc.perform(get("/people"));
to make it run, I think need to give value to mockMvc first.
by constructor :
#Test
public void testPeople() throws Exception {
mockMvc = new MockMvc();
// When
ResultActions actions = mockMvc.perform(get("/people"));
}
or Autowired :
#Autowired
MockMvc mockMvc
depends on the purpose of MockMvc Class
I have a working integration test for my Spring Web MVC app that looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = ShibaApplication.class)
#WebAppConfiguration
public class EchoControllerTests {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
private void setup() throws Exception {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
#Test
public void echo() throws Exception {
mockMvc.perform(get("/echo/blargh"))
.andExpect(status().isOk())
.andExpect(content().string("blargh"));
}
}
Leaving that (successful) test in place, I tried to create an identical Cucumber test. The Cucumber runner is:
#RunWith(Cucumber.class)
#CucumberOptions(features="src/test/resources",
glue={"co.masslab.shiba", "cucumber.api.spring"})
public class CucumberTests {
}
The class that defines the Cucumber steps looks like:
#WebAppConfiguration
#Import(ShibaApplication.class)
#ContextConfiguration(classes=CucumberTests.class)
public class WebStepDefs {
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
private ResultActions resultActions;
#When("^the client calls the echo endpoint$")
public void the_client_calls() throws Exception {
Assert.notNull(webApplicationContext);
this.mockMvc = webAppContextSetup(webApplicationContext).build();
this.resultActions = mockMvc.perform(get("/echo/blargh"));
}
#Then("^the client receives a status code of 200$")
public void the_client_receives_a_status_code() throws Exception {
resultActions.andExpect(status().isOk());
}
}
However, the cucumber test fails, as the result is not a 200 but a 404.
I suspect this is because the WebApplicationContext getting autowired into the WebStepDefs class isn’t the same as the one that gets autowired into the EchoControllerTests. I’ve been going over the Spring JavaConfig Reference Guide v1.0.0.M4, but I haven’t yet figured out where I’m going wrong.
I kept trying different combinations of annotations, and finally figured this one out. The annotations for WebStepsDef that worked for me were:
#ContextConfiguration(classes=ShibaApplication.class, loader=SpringApplicationContextLoader.class)
#IntegrationTest
#WebAppConfiguration