I am doing controller integration testing. A controller with a get mapping returns Flux.
#Slf4j
#RequiredArgsConstructor
#RequestMapping("journal")
public class EntryController {
private final SomeService someService;
#GetMapping
public Flux<MyEntity> getEntity(
#RequestParam(required = false) String documentId,
#RequestParam(required = false) String docNumber){
return someService.getEntities( GetEntriesRequest.builder()
.documentId(documentId)
.docNumber(docNumber).build;
}
#PostMapping
public MyEntity postNew(#RequestBody #Valid MyEntity entity) {
return someService.save(entity);
}
}
.
Initially, I tried to test it like this. (method asJson remakes the Entity created by creatingEntity method in a Json format). I'm already tested a controller with a post mapping and it works right.
#Test
void getEntriesByDocumentNumber() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(post("/journal")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJson(creatingEntity())))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andReturn();
String response = mvcResult.getResponse().getContentAsString();
String documentIdFromResponse =
JsonPath.parse(response).read("$.documentId");
this.mockMvc.perform(get("/journal")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.param("documentId", documentIdFromResponse))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk());
I do not know how to process the response that I receive. The fact is that the response body is empty, but the method works, this can be seen in the async result. I did not find how to get the asinc result. And I can’t use JsonPath, because the body is empty.
HTTP Method = GET
Request URI = /journal
Parameters = {documentId=[1590067372983-9ce4f563-520d-42ff-bd31-5b78befaf4b1]}
Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json"]
Body = null
Session Attrs = {}
Async:
Async started = true
Async result = [MyEntity(documentId=1590067372983-9ce4f563-520d-42ff-bd31-5b78befaf4b1, documentNumber=100)]
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
I try to use WebTestClient, But this code does not work. It's falling with No bean named 'webHandler' available
#SpringBootTest
#AutoConfigureMockMvc
class ApplicationTests {
#Autowired
private MockMvc mockMvc;
WebTestClient webTestClient;
#BeforeEach
void setUp(ApplicationContext context) {
webTestClient = WebTestClient.bindToApplicationContext(context).build();
}
#Test
void getEntityTest() throws Exception {
MvcResult mvcResult = this.mockMvc.perform(post("/journal")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJson(creatingEntity())))
.andDo(MockMvcResultHandlers.print())
.andExpect(status().isOk())
.andReturn();
String response = mvcResult.getResponse().getContentAsString();
String documentIdFromResponse = JsonPath.parse(response).read("$.documentId");
webTestClient.get()
.uri("journal/")
.accept(MediaType.APPLICATION_JSON)
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath("$[0].documentId").isEqualTo(documentIdFromResponse);
}
}
I'm already find this. But I don't know how to use it
#Bean
public WebHandler webHandler() {
//implement your bean initialization here
}
Related
The content from MockMvc managed to have status code but missing the data.
Test class:
#Test
public void shouldReturnAll() throws Exception {
when(userService.getAll()).thenReturn(users); // note that 'users' is not empty, I already checked.
MvcResult response = this.mvc.perform(get("/users"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data", hasSize(2)))
.andReturn();
}
Reponse:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = {"status":"success"}
Forwarded URL = null
Redirected URL = null
Cookies = []
I think it has something to do with Response object in my Controller class.
Controller:
#GetMapping
public ResponseEntity<Response> getAll() {
List<User> users = userService.getAll();
Response resp = new Response(StatusMessage.SUCCESS, users);
return new ResponseEntity<Response>(resp, HttpStatus.OK);
}
Edit: Another test which works (getting a single User):
#Test
public void getUserByIdTest() throws Exception {
when(this.userService.getUserById(any(Long.class))).thenReturn(user);
MvcResult response = this.mvc.perform(get("/users/{id}", user.getId()))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.id", is(user.getId().intValue())))
.andExpect(jsonPath("$.data.name", is(user.getName())))
.andReturn();
}
Controller:
#GetMapping(value = "/{id}")
public ResponseEntity<Response> getUserById(#PathVariable Long id) throws Exception {
try {
User user = userService.getUserById(id);
Response resp = new Response(StatusMessage.SUCCESS, user);
return new ResponseEntity<Response>(resp, HttpStatus.OK);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
}
Response object class:
#Data
#JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Response<T> {
private String status;
private T data;
public Response(StatusMessage status, T data) {
this.status = status.getStatusMessage();
this.data = data;
}
I have a servlet defined in web.xml, so I defined it inside a Controller for testing only for MyResource:
#Controller
public class TestMyServlet {
MyResource servlet;
#Autowired
AutowireCapableBeanFactory beanFac;
#PostConstruct
void init() {
servlet = new MyResource();
beanFac.autowireBean(servlet);
}
#RequestMapping(value = "/servlet/api/update", method = RequestMethod.POST)
public MyResponse handle(HttpServletRequest request, HttpServletResponse response, #RequestBody String json) {
return servlet.update(json);
}
Then I test it using MockHttpServletRequestBuilder:
MockHttpServletRequestBuilder mockHttpServletRequestBuilder = MockMvcRequestBuilders
.post("/servlet/api/update")
.content("{\"id\":1,\"toggle\":true}]")
.session(httpSession)
.contentType(MediaType.APPLICATION_JSON);
MvcResult mvcResult = this.mockMvc.perform(mockHttpServletRequestBuilder)
.andDo(MockMvcResultHandlers.print())
.andReturn();
ModelAndView modelAndView = mvcResult.getModelAndView().getModelMap();
String response = mvcResult.getResponse().getContentAsString();
In servlet I don't use ModelAndView, just returning a POJO object (MyResponse) that is serialize to JSON response
I'm seeing MyResponse object as a second attribute in ModelAndView, but response is null
How can I check JSON string returned in this response?
There is one way here, i hope i understood the question correct ,
MockMvcRequestBuilders
.post("/servlet/api/update")
.content("{\"id\":1,\"toggle\":true}]")
.session(httpSession)
.contentType(MediaType.APPLICATION_JSON)
.andExpect(jsonPath("$[0].key",is("value")));
andExpect(jsonPath("$[0].key",is("value")))
you can use this for each key and value.
Or
try this ,
MockMvcRequestBuilders
.post("/servlet/api/update")
.content("{\"id\":1,\"toggle\":true}]")
.session(httpSession)
.contentType(MediaType.APPLICATION_JSON)
.andExpect(content().string(containsString("value")));
I am doing the integration tests on a REST api where all the tests work but this one.
#Test
public void deleteAllUsers_should_return_noContent() throws Exception {
//Given
//When
ResultActions resultActions = mockMvc
.perform(delete("/pair?delAll"));
//Then
resultActions
.andDo(print())
.andExpect(status().isNoContent());
}
I am expecting a 204 http status but it gets a 400. Here is the code for the method:
#RequestMapping(value = "/pair", method = RequestMethod.DELETE, params = "delAll")
public ResponseEntity<Void> deleteAllUsers() {
userRepository.deleteAll();
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
Any ideas to what am I doing wrong?
EDIT: Found the solution just adding "=true" to these lines
#RequestMapping(value = "/pair", method = RequestMethod.DELETE, params = "delAll=true")
ResultActions resultActions = mockMvc
.perform(delete("/pair?delAll=true"));
I am trying to test a basic controller:
#Autowired
DAOInterface db;
#RequestMapping(value = "/postdb", method = RequestMethod.GET)
#ResponseBody
public String postdb(
#RequestParam(value = "id", required = true) String id
) {
db.addEntry(id);
return "Added " + id + ".";
}
This url works as when I access it, it adds it to a db and I get the string output as a response.
I am trying to create a simple unit test for it:
#Autowired
MockMvc mockMvc;
#MockBean
DAOInterface daoInterface;
#Test
public void shouldReturnA200() throws Exception {
mockMvc.perform(get("/postdb?id=3"))
.andExpect(status().isOk());
}
But instead I get the following
MockHttpServletRequest:
HTTP Method = GET
Request URI = /postdb
Parameters = {id=[3]}
Headers = {}
Handler:
Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 404
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :404
Not sure why I it's working whenever I try and access it but fails when running this test. I don't see any issues. Might it be because I'm not using any headers or a formal response body/view and rather just outputting a String?
EDIT = It works when I add
.contextPath("/postdb")).. not sure if that's the correct way but when I write another test and dont include any request paramters, that test gives a 200 instead of a 400 or 404....
#Autowired
DAOInterface db;
#RequestMapping(value = "/postdb", method = RequestMethod.GET)
public ResponseEntity<String> postdb(#RequestParam(required = true) String id) {
db.addEntry(id);
return new ResponseEntity<>("Added " + id + ".", HttpStatus.OK);
}
Test:
#Test
public void shouldReturnA200() throws Exception {
mockMvc.perform(get("/postdb?id=3")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
}
Below is working fine for me
public class FirstWebController {
#RequestMapping(value = "/postdb", method = RequestMethod.GET)
#ResponseBody
public String postdb(#RequestParam(value = "id", required = true) String id) {
System.out.println("idddddddddddd "+id);
return "Added " + id + ".";
}
}
Test class is
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class FirstWebControllerTest {
#Configuration
static class FirstWebControllerTestConfiguration {
#Bean
public FirstWebController firstWebController() {
return new FirstWebController();
}
}
#Autowired
private FirstWebController firstWebController;
private MockMvc mockMvc;
#Before
public void setup() {
mockMvc = standaloneSetup(firstWebController).build();
}
#Test
public void shouldReturnA200() throws Exception {
mockMvc.perform(get("/postdb?id=3")).andExpect(status().isOk());
}
}
Try adding query parameter as below:
#Test
public void shouldReturnA200() throws Exception {
mockMvc.perform(get("/postdb).param("id", "3"))
.andExpect(status().isOk());
}
I have a controller:
#Controller
#RequestMapping(value = "/bookForm")
public class BookFormController {
#Autowired
private BookHttpRequestParser parser;
#Autowired
private BooksService booksService;
#RequestMapping(params = "add", method = RequestMethod.POST)
public String addBook(HttpServletRequest request) {
try {
Book newBook = parser.createBookFromRequest(request);
booksService.addBook(newBook);
} catch (InvalidTypedParametersException e) {
}
return "redirect:index.html";
}
This Controller has a method for adding book to DB. Method has #RequestMapping annotation with params = "add" value.
Im trying to set this params criteria to controller unit test method:
#Test
public void addBook() throws Exception{
HttpServletRequest request = mock(HttpServletRequest.class);
Book book = new Book();
when(parser.createBookFromRequest(request)).thenReturn(book);
mockMvc.perform(post("/bookForm", "add"))
.andExpect(status().isOk())
.andExpect(view().name("redirect:index.html"));
}
Where to specify this #ResuetsMapping params value?
This:
mockMvc.perform(post("/bookForm", "add"))
doesn't work at all.
The following should work.
mockMvc.perform(post("/bookForm?add="))
use RequestBuilder requestBuilders;
object to build your request
requestBuilders = MockMvcRequestBuilders.get("URL/{Pathvariable}","PathvariableValue")
.contentType(MediaType.APPLICATION_JSON)
.header("HeaderName", HeaderValue)
.param("ParameterName", "Value")
.param("ParameterName", "Value")
.accept(MediaType.APPLICATION_JSON);
and the perfrom
mockMvc.perform(requestBuilders)
.andDo(print())
.andExpect(status().isOk())
.andReturn();