When using MockMvc to test the controller, a parameter passing error occurred - spring

I am using MockMvc to test the controller. Regarding parameter import, I encountered a type mismatch problem. I tried all the json styles.But nothing works
This is my controller class::
package app.dnatask.controller;
import ......;
#Slf4j
#RestController
#RequestMapping(value = "/API/scanresultconfigure")
public class ScanResultConfigureController extends BaseController {
#RequestMapping(value = "/queryScanResultList/{taskId}/{externalname}", method = RequestMethod.POST)
public IBaseResult queryscanResultList(final HttpServletRequest request, #PathVariable final String taskId, #PathVariable final String externalname, #RequestBody Map map) throws Exception {
return runController(new IControllRunner() {
public void run(IOutResult or, CheckResult cr) throws Exception {
......
}
}
}
}
This is my test class::
package app.dnatask.controller;
import ......
#WebAppConfiguration
#ContextConfiguration(classes = {ScanResultConfigureController.class})
#ComponentScan(
includeFilters = {
#ComponentScan.Filter(type = FilterType.CUSTOM,
value = {ScanResultConfigureController.class})
},
useDefaultFilters = false,
lazyInit = true
)
public class ScanResultConfigureControllerTest extends AbstractTestNGSpringContextTests {
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#BeforeMethod
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).dispatchOptions(true).build();
System.out.println("UT starting.............");
}
#AfterMethod
public void am() {
System.out.println("UT ending.............");
}
#Test
public void testQueryscanResultList() throws Exception {
Map<String, String> testMap = new HashMap<>();
testMap.put("key1", "value1");
testMap.put("key2", "value2");
String requestJson = JSONObject.toJSONString(testMap);
mockMvc.perform(
post("/API/scanresultconfigure/queryScanResultList/001/abc")
.contentType(MediaType.APPLICATION_JSON)
.param("map", requestJson)
)
.andExpect(status().isOk())
.andDo(print());
}
}
Error message::
org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json' not supported
java.lang.AssertionError: Status expected:<200> but was:<415>
This is a project implemented by springmvc framework, I use TestNG for unit testing.

Regarding my problem, the solution is as follows::
MvcResult mvcResult = mockMvc.perform(
post("/API/scanresultconfigure/queryScanResultList/{taskId}/{externalname}", "123", "abc")
.contentType(MediaType.APPLICATION_JSON)
.content(requestJson)
)
.andExpect(status().isOk())
.andDo(print())
.andReturn();

Related

Why Testing Controller not working with #RunWith(SpringRunner.class) & #WebMvcTest annotation?

I am getting the below error when I try to run my controller test. Please can you let me know what I am missing? Why should I add the #ContextConfiguration or #SpringBootTest ?
java.lang.IllegalStateException: Unable to find a #SpringBootConfiguration, you need to use #ContextConfiguration or #SpringBootTest(classes=...) with your test
#Controller
public class BasketController {
#Autowired
private BasketService basketService;
#GetMapping(value="/baskets/{basketId}")
public ResponseEntity<BasketDto> getBasket(#PathVariable("basketId") UUID basketId){
Basket basket = basketService.getBasket(basketId);
BasketDto dto = toBasketDto(basket);
ResponseEntity response = ResponseEntity.status(HttpStatus.OK).body(dto);
return response;
}
private BasketDto toBasketDto(Basket basket){
BasketDto dto = new BasketDto(basket.getBasketId(), basket.getItems());
return dto;
}
}
#RunWith(SpringRunner.class)
#WebMvcTest(BasketController.class)
public class BasketControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private BasketService basketService;
#Test
public void testGetItemsInBasketSuccessfully() throws Exception {
UUID basketId = UUID.randomUUID();
String URI = "/api/baskets/" + basketId;
Basket mockBasket = new Basket(basketId);
Mockito.when(basketService.getBasket(basketId)).thenReturn(mockBasket);
RequestBuilder requestBuilder = MockMvcRequestBuilders.get(URI).accept(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
String actualJson = result.getResponse().getContentAsString();
System.out.println(actualJson);
}
}

MockMvc response returns 404, expected response 201

I am new to unit testing REST API in Spring Boot.
I am expecting response status as CREATED but instead I am getting a PAGE NOT FOUND error.
Below is the code for:-
UserControllerUnitTests
#SpringBootTest
#ContextConfiguration(classes = { CommonConfig.class, SecurityConfig.class})
#RunWith(SpringRunner.class)
class UserControllerUnitTests {
private static ObjectMapper mapper;
private static final String URI = "/users";
MockMvc mvc;
#Autowired
WebApplicationContext webAppContext;
#Mock
UserService userService;
MvcResult mvcResult;
#BeforeAll
static void setUp() {
mapper = new ObjectMapper();
}
#BeforeEach
void initialize() throws Exception {
mvc = MockMvcBuilders.webAppContextSetup(webAppContext).build();
....
....
....
void shouldReturnStatusCreatedIfValidUserPassedForPostUser(long index) throws Exception {
int expectedStatus = HttpStatus.CREATED.value();
UserDAO returnUser;
UserDAO user = userList.get(index);
userList.remove(index);
String jsonContent = mapper.writeValueAsString(user);
user.setId(index);
user.setEncryptedPassword(null);
Mockito.when(userService.addUser(Mockito.any())).thenReturn(user);
mvcResult = mvc.perform(MockMvcRequestBuilders.post(URI)
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(jsonContent)).andReturn();
//Mockito.verify(userService, Mockito.times(1)).addUser(Mockito.any());
int actualStatus = mvcResult.getResponse().getStatus();
Assert.assertEquals("Response status should be CREATED", expectedStatus, actualStatus);
jsonContent = mvcResult.getResponse().getContentAsString();
returnUser = mapper.readValue(jsonContent, UserDAO.class);
Assert.assertEquals("EncryptedPassword should not be returned", null,
returnUser.getEncryptedPassword());
}
User Controller.class
#RestController
#RequestMapping("users/")
public class UserController {
UserService userService;
#Autowired
public UserController(UserService userService) {
this.userService = userService;
}
....
....
....
#PostMapping(path = "",
consumes = { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON },
produces = { MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public ResponseEntity<UserDAO> createUser(#Valid #RequestBody UserDAO user) {
String password = user.getEncryptedPassword();
user.setEncryptedPassword(null);
UserDAO retreivedUser;
if(user.getId() != 0)
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
user.setEncryptedPassword(password);
retreivedUser = userService.addUser(user);
if(retreivedUser != null)
return new ResponseEntity<>(retreivedUser, HttpStatus.CREATED);
return new ResponseEntity<>(HttpStatus.CONFLICT);
}
}
The full code can be found at https://github.com/vineethmaller/springboot-userservice
I spotted a few errors:
Get rid of ContextConfiguration
#SpringBootTest
// #ContextConfiguration(classes = { CommonConfig.class, SecurityConfig.class})
#RunWith(SpringRunner.class)
class UserControllerUnitTests {
Specify correct mapping on the controller (no slash)
#RestController
#RequestMapping("users")
public class UserController {
You setup your UserService mock which is not used in the test. Did you mean #MockBean?
#MockBean
UserService userService;

Testing the controller which returns response entity

I have following the controller which accepts post request and returns Response Entity with body
#RestController
public class UserController {
#Autowired
private UserService UserService;
#RequestMapping(value = "/all", method = POST,consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ResponseUser>> navigationTree(#RequestBody(required=false) UserDataRequest request) {
return UserService.sendEntries(request);
}
}
This is the test I wrote I for it:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class UserControllerTest {
private MockMvc mockMvc;
#MockBean
private UserService UserServiceMock;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setUp() {
this.mockMvc = webAppContextSetup(webApplicationContext).build();
}
#Test
public void returnTopLevel() throws Exception {
String expectedJson = "[{\"id\":\"11\",\"name\":\"11\"},{\"id\":\"22\",\"name\":\"22\"}]";
MvcResult result = this.mockMvc.perform(post("/all")
.contentType(MediaType.APPLICATION_JSON)
.content("")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andReturn();
String actualJson = result.getResponse().getContentAsString();
// System.out.println(result);
//assertThat(Objects.equals(expectedJson, actualJson)).isTrue();
verify(UserServiceMock,times(1)).sendEntries(null);
}
}
I want to compare string received in response body to expected string.
I tried the string comparison but it's not working
Errors :
assertThat(Objects.equals(expectedJson, actualJson)).isTrue();
and actualjson is empty.
What are the other ways?
You need to mock the UserService to return something before executing this.mockMvc.perform. Something like this:
when(UserServiceMock.sendEntries(null)).thenReturn(expectedResponceEntity);
So just construct the expected response then mock UserService to return it.

Spring boot - integration testing - WebTestClient & HttpServletRequest

I'm having difficulties figuring this out.
I can mock almost everything but for some reason the HttpServletRequest is mocked but not injected into the #ControllerAdvice #ExceptionHandler method.
Any ideas? Thank you for your help in advance!
STR Repo with minimal plug and play test suite / code
https://github.com/krodyrobi/spring-integration-test-str
#Component
public class Config {
private final String url = "https://httpstat.us/";
public String getUrl() {
return url;
}
}
#RestControllerAdvice
public class GlobalExceptionHandler {
#ExceptionHandler(WebClientResponseException.class)
public ResponseEntity<String> handleException(HttpServletRequest request, WebClientResponseException ex) {
return new ResponseEntity<>(request.getRequestURL() + " " + ex.getResponseBodyAsString(), ex.getStatusCode());
}
}
#RestController
public class SomeController {
private final Config config;
#Autowired
public SomeController(Config config) {
this.config = config;
}
#GetMapping("/test")
public Mono<String> test() {
return WebClient
.create(config.getUrl())
.get()
.uri("/200")
.retrieve()
.bodyToMono(String.class);
}
}
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {
SomeController.class,
GlobalExceptionHandler.class,
})
public class SomeControllerTest {
private final static String baseUrl = "http://localhost:9999/";
public #Rule WireMockRule wireMockRule = new WireMockRule(9999);
private #MockBean Config config;
private #MockBean HttpServletRequest request;
private WebTestClient webClient;
private #Autowired SomeController controller;
private #Autowired GlobalExceptionHandler exceptionHandler;
#Before
public void setUp() {
webClient = WebTestClient
.bindToController(controller)
.controllerAdvice(exceptionHandler)
.build();
when(config.getUrl()).thenReturn(baseUrl);
}
#Test
public void test_works() {
wireMockRule
.stubFor(get(urlEqualTo("/200"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "text/plain")
.withBody("200 MOCK")));
webClient
.get()
.uri("/test")
.exchange()
.expectStatus()
.isOk()
.expectBody(String.class)
.isEqualTo("200 MOCK");
wireMockRule.verify(getRequestedFor(urlMatching("/200")));
}
#Test
public void test_fails() {
// java.lang.IllegalStateException: No suitable resolver for argument 0
// of type 'javax.servlet.http.HttpServletRequest' on public
// org.springframework.http.ResponseEntity<java.lang.String>
// com.example.demo.GlobalExceptionHandler.handleException(
// javax.servlet.http.HttpServletRequest,
// ...client.WebClientResponseException
// )
wireMockRule
.stubFor(get(urlEqualTo("/200"))
.willReturn(aResponse()
.withStatus(404)
.withHeader("Content-Type", "text/plain")
.withBody("404 MOCK")));
webClient
.get()
.uri("/test")
.exchange()
.expectStatus()
.isNotFound()
.expectBody(String.class)
.isEqualTo("Http://localhost:8080/test 404 MOCK");
wireMockRule.verify(getRequestedFor(urlMatching("/200")));
}
}
Use below instead of HttpServletRequest
import org.springframework.http.server.reactive.ServerHttpRequest;
ServerHttpRequest request

Setting session attributes for JUnits on Spring 3.2

I'm having trouble setting session attributes for a test. I am using MockMvc to test calls to a controller. The session model has a member attribute on it (representing the person who has logged in). The SessionModel object is added as a session attribute. I was expecting it to be populated in the ModelMap parameter to formBacking method below, but the ModelMap is always empty.
The controller code works fine when running through the webapp, but not in the JUnit. Any idea what I could be doing wrong?
Here is my JUnit Test
#Test
public void testUnitCreatePostSuccess() throws Exception {
UnitCreateModel expected = new UnitCreateModel();
expected.reset();
expected.getUnit().setName("Bob");
SessionModel sm = new SessionModel();
sm.setMember(getDefaultMember());
this.mockMvc.perform(
post("/units/create")
.param("unit.name", "Bob")
.sessionAttr(SessionModel.KEY, sm))
.andExpect(status().isOk())
.andExpect(model().attribute("unitCreateModel", expected))
.andExpect(view().name("tiles.content.unit.create"));
}
and here is the controller in question
#Controller
#SessionAttributes({ SessionModel.KEY, UnitCreateModel.KEY })
#RequestMapping("/units")
public class UnitCreateController extends ABaseController {
private static final String CREATE = "tiles.content.unit.create";
#Autowired
private IUnitMemberService unitMemberService;
#Autowired
private IUnitService unitService;
#ModelAttribute
public void formBacking(ModelMap model) {
SessionModel instanceSessionModel = new SessionModel();
instanceSessionModel.retrieveOrCreate(model);
UnitCreateModel instanceModel = new UnitCreateModel();
instanceModel.retrieveOrCreate(model);
}
#RequestMapping(value = "/create", method = RequestMethod.GET)
public String onCreate(
#ModelAttribute(UnitCreateModel.KEY) UnitCreateModel model,
#ModelAttribute(SessionModel.KEY) SessionModel sessionModel) {
model.reset();
return CREATE;
}
#RequestMapping(value = "/create", method = RequestMethod.POST)
public String onCreatePost(
#ModelAttribute(SessionModel.KEY) SessionModel sessionModel,
#Valid #ModelAttribute(UnitCreateModel.KEY) UnitCreateModel model,
BindingResult result) throws ServiceRecoverableException {
if (result.hasErrors()){
return CREATE;
}
long memberId = sessionModel.getMember().getId();
long unitId = unitService.create(model.getUnit());
unitMemberService.addMemberToUnit(memberId, unitId, true);
return CREATE;
}
}
For your test class add the #WebAppConfiguration annotation and autowire the following as well.(WebApplicationContext and MockHttpSession )
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration({ "classpath:springDispatcher-servlet.xml" })
public class MySessionControllerTest {
#Autowired WebApplicationContext wac;
#Autowired MockHttpSession session;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void testUnitCreatePostSuccess() throws Exception {
UnitCreateModel expected = new UnitCreateModel();
expected.reset();
expected.getUnit().setName("Bob");
SessionModel sm = new SessionModel();
sm.setMember(getDefaultMember());
session.setAttribute(SessionModel.KEY, sm);
this.mockMvc.perform(
post("/units/create")
.session(session)
.param("unit.name", "Bob")
.andExpect(status().isOk())
.andExpect(model().attribute("unitCreateModel", expected))
.andExpect(view().name("tiles.content.unit.create"));
}
}

Resources