Spring MVC test with MockMvc - java

I'm trying to run a test for testing a Spring MVC controller. The test compile and runs, but my problem is that I got a PageNotFound warning:
WARN PageNotFound - No mapping found for HTTP request with URI [/] in DispatcherServlet with name ''
My really simple test as follows:
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration({
"classpath*:/WEB-INF/applicationContext.xml",
"classpath*:/WEB-INF/serviceContext.xml"
})
public class FrontPageControllerTest {
#Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
#Before
public void init() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.ctx).build();
}
#Test
public void frontPageController() throws Exception {
this.mockMvc.perform(get("/"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(view().name("searchfrontpage"));
}
}
I'm 100% sure that my webapp maps to the frontpage at "/" and that the name on the view is "searchfrontpage".
Please help!

Another easier way to solve the issue is to change init to this :
mockMvc = MockMvcBuilders.standaloneSetup(new FrontPageController()).build();

My ContextConfiguration was wrong. Correct was:
#ContextConfiguration({
"file:src/main/webapp/WEB-INF/applicationContext.xml",
"file:src/main/webapp/WEB-INF/serviceContext.xml"
})
Now everything works fine.

Related

java.lang.IllegalStateException: Configuration error

Found that IllegalStateException is used to indicate that "a method has been invoked at an illegal or inappropriate time." Now, while doing JUnit testing I found this error. Any help?
N.B: I am beginner in Java Spring Boot Framework. So, solution can be simple one.
found multiple declarations of #BootstrapWith for test class [com.jrp.pma.controller.HttpRequestTest]: [#org.springframework.test.context.BootstrapWith(value=org.springframework.boot.test.context.SpringBootTestContextBootstrapper), #org.springframework.test.context.BootstrapWith(value=org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper)]
package com.jrp.pma.controller;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.jupiter.api.Assertions.assertEquals;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
//#DataJpaTest
public class HttpRequestTest {
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
public void homePageReturnsVersionNumberCorrectly_thenSuccess(){
String renderHtml = this.restTemplate.getForObject("http://localhost:" + port + "/", String.class);
assertEquals(renderHtml.contains("3.3.3"), false);
}
}

MockMvc Not working when Controller is in different package (JUnit5)

package com.azry.ptm.api;
import com.azry.ptm.api.model.account.AccountDTO;
import com.azry.ptm.domain.account.Account;
import com.azry.ptm.server.services.AccountService;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.anyLong;
#AutoConfigureMockMvc
#SpringBootTest
public class AccountControllerImplTest {
#Autowired
private MockMvc mockMvc;
#MockBean
public AccountService accountService;
#Test
public void test() throws Exception {
final long entityNo = 10;
Account expectedAccount = Account.builder()
.entityNo(entityNo)
.build();
Mockito.when(accountService.getAccountById(anyLong())).thenReturn(Optional.of(expectedAccount));
MockHttpServletResponse response = mockMvc.perform(ControllerTestHelper.makeGetRequest("account/", String.valueOf(entityNo)))
.andReturn()
.getResponse();
AccountDTO responseAccount = ControllerTestHelper.toObject(response.getContentAsString(), AccountDTO.class);
assertEquals(HttpStatus.OK.value(), response.getStatus());
assertNotNull(responseAccount);
}
}
Here is my mockMvc test. it works only when the controller is in the same module es test, otherwise, when I split the project it returns a 404 error code as no endpoint was found.
has anybody experience using mockMvc in a multi-module spring-boot app?
solved using #WebMvcTest annotation
#WebMvcTest(AccountControllerImpl.class)

Mapping two #GetMapping to same #RestController into Spring Boot

I need to mapping two GET methods look like:
GET /tickets - Retrieves a list of tickets
GET /tickets/12 - Retrieves a specific ticket
But when I mapped this, the Spring got confused!
When I hit http://localhost:8080/tickets in the Chrome, the result on server is:
DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "tickets"]
When I hit http://localhost:8080/tickets/12 in the Chrome, the result on server is:
QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
My Spring controller is:
package wendelsilverio.api.ticket;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
#RestController("tickets")
public class TicketController {
#Autowired
private TicketRepository repository;
#GetMapping
public List<TicketEntity> getTickets() {
return repository.findAll();
}
#GetMapping("/{id}")
public Optional<TicketEntity> getTicket(#PathVariable("id") Long id) {
return repository.findById(Long.valueOf(id));
}
}
My unit test is:
package wendelsilverio.api.ticket;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.Arrays;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
#SpringBootTest
#AutoConfigureMockMvc
#RunWith(SpringRunner.class)
public class TicketControllerRestfulTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private TicketController mockTicketController;
#Test
public void getTickets() throws Exception {
given(mockTicketController.getTickets())
.willReturn(Arrays.asList(new TicketEntity(1L, "First ticket"), new TicketEntity(2L, "Second ticket")));
mockMvc.perform(get("tickets").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$[0].content", is("First ticket")))
.andExpect(jsonPath("$[1].content", is("Second ticket")));
}
#Test
public void getTicket12() throws Exception {
Optional<TicketEntity> twelveTicket = Optional.of(new TicketEntity(12L, "Twelve ticket"));
given(mockTicketController.getTicket(12L)).willReturn(twelveTicket);
mockMvc.perform(get("tickets/12").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$.id", is(12L))).andExpect(jsonPath("$.content", is("Twelve ticket")));
}
}
I'm using Java 11 and Spring Boot 2.1.6
Use
#RestController
#RequestMapping("/tickets")
...
#GetMapping
...
#GetMapping("{id}")
In your code
1) #RestController("tickets") means 'create bean named "tickets"'
2) second URL (#GetMapping("/{id}")) tells 'put ID at root' (http://localhost:8080/ID) - so controller cannot convert 'tickets' to long.

How to test mvc controller method with http response argument?

Can you help me? I need to test this controller method. But don't know what to do with httpservletresponse object.
#Controller
public class HomeController {
#PostMapping("/signout")
public String signOut(HttpServletResponse response){
response.addCookie(new Cookie("auth-token", null));
return "redirect:http://localhost:3000";
}
}
Thank you)
Spring MVC Test provides an effective way to test controllers by performing requests and generating responses through the actual DispatcherServlet.
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultMatcher;
#RunWith(SpringRunner.class)
#WebMvcTest(controllers=HomeController.class)
public class HomeControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void testSignOut() throws Exception {
mockMvc.perform(post("/signout"))
.andDo(print())
.andExpect(new ResultMatcher() {
#Override
public void match(MvcResult result) throws Exception {
Assert.assertEquals("http://localhost:3000",result.getResponse().getRedirectedUrl());
}
});
}
}
In case of Spring MVC without spring boot, use standalone MockMvc support
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration // or #ContextConfiguration
public class HomeControllerTest{
#Autowired
private HomeController homeController;
private MockMvc mockMvc;
#Before
public void setup() {
// Setup Spring test in standalone mode
this.mockMvc =
MockMvcBuilders.standaloneSetup(homeController).build();
}

Unit tests in Spring MVC Rest - cast issue

I am developing simple Rest API app and trying to test it using this tutorial: http://memorynotfound.com/unit-test-spring-mvc-rest-service-junit-mockito/
I have implemented entire test_get_all_success unit test using my working Rest API (written in Spring MVC). Unfortunately test cannot run because of following issue.
Here is entire test file:
import java.util.Arrays;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.Matchers.*;
import org.junit.Before;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.*;
import org.mockito.MockitoAnnotations;
import org.springframework.http.MediaType;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={MyConfigClass.class})
#WebAppConfiguration
public class ClientTest {
private MockMvc mockMvc;
#Mock
private ClientManagerImpl clientManager;
#InjectMocks
private ClientController clientController;
#Before
public void init(){
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(clientController)
.build();
}
#Test
public void findAll_ClientsFound_ShouldReturnFoundClients() throws Exception {
Client a = ...;
Client b = ...;
when(clientManager.getClients()).thenReturn(Arrays.asList(a, b));
mockMvc.perform(get("/clients"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$", hasSize(2)));
verify(clientManager, times(1)).getClients();
verifyNoMoreInteractions(clientManager);
}
}
NetBeans shows error in this line:
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
incompatible types: RequestMatcher cannot be converted to ResultMatcher
Test cannot run because of this error. When I delete this line everything works fine and test is passed.
What am I doing wrong?
The following static import causes the conflict:
import static org.springframework.test.web.client.match.MockRestRequestMatchers.content;
MockRestRequestMatchers class is used for client-side REST testing using MockRestServiceServer, but you are testing here MVC application controllers.

Categories