java.lang.AssertionError: Status expected:<200> but was:<201> - java

Hi I'm trying to implement junit in my controller. But what I get is 201 instead of 200.
Below is my controller
#RestController
#RequestMapping(value = "/treat")
public class TreatController {
private final TreatService treatService;
#Autowired
public TreatController(TreatService treatService){
this.treatService = treatService;
}
#PostMapping
public ResponseEntity<CommonResponse> addNew(
#RequestBody Treat treat) throws RecordNotFoundException{
CommonResponse response = new CommonResponse();
response.setStatus(CommonConstants.OK);
response.setData(treatService.save(treat));
return new ResponseEntity<>(response, HttpStatus.CREATED);
}
}
next is my Junit testing:
#RunWith(SpringJUnit4ClassRunner.class)
#WebMvcTest(TreatController.class)
public class TreatControllerTest {
private RecordNotFoundException recordException = new RecordNotFoundException("");
private final String title = "{\"title\" : \"title\"}";
#Autowired
private MockMvc mockMvc;
#MockBean
private TreatService treatService;
#Test
public void addNew() throws Exception{
Treatment treatment = new Treatment();
given(treatmentService.save(
Mockito.any(Treat.class))).willReturn(treat);
mockMvc.perform(post("/treats")
.content(title)
.accept(MediaType.APPLICATION_JSON_VALUE)
.contentType(MediaType.APPLICATION_JSON_VALUE))
.andDo(print())
.andExpect(status().isOk());
Mockito.verify(treatService).save(Mockito.any(Treat.class));
}
}
is there anything that I missed?
By the way, I dont use Json. I just inserted it because it works.

That's what you return.
return new ResponseEntity<>(response, HttpStatus.CREATED);
HttpStatus.CREATED returns 201 and indicates that a resource has been created by the request
How ever in your testcase you are expecting OK(200) .andExpect(status().isOk());
According to HTTP1.1/ specs Post request should always result in the creation of a resource. So it makes sense to return 201 from there. All your need to do is change your testcase assertion expected value to HTTPStatus.CREATED.

Related

Junit Test case Spring boot controller returning null value in ResponseEntity

In my project I am creating a rest endpoint which is responsible to consume grpc service response.
Now I want to write testcase for the controller class but the Junit test cases returning me null null values .
MyController.java
#RestController
#RequestMapping("/v1")
public class MyController {
#Autowired
private MyConsumerService consumer;
public MyController(MyConsumerService consumer) {
this.consumer=consumer;
}
#GetMapping("/data")
public ResponseEntity<Records> getData(#RequestParam("data") String data) {
Records records = consumer.getGrpcResponse(data);
return new ResponseEntity<>(Records, HttpStatus.OK);
}
}
MyConsumerServiceImpl.java:
public class MyConsumerServiceImpl implements MyConsumerService {
#GrpcClient("user-grpc-service")
private userGrpc.userBlockingStub stub;
#Override
public Records getGrpcResponse(data) {
Records records = new Records();
UserRequest request = UserRequest.newBuilder()
.setUserName(data)
.build();
APIResponse response = stub.userRequest(request);
records.setUserName(response.getUserName());
return records;
}
}
MyControllerTest.java:
#ExtendWith(MockitoExtension.class)
public class MyControllerTest {
private MyConsumerService mockerService;
private MyController controller;
#BeforeEach
void setup(){
mockerService = mock(MyConsumerService.class);
controller = new MyController(mockerService);
}
#Test
public void shouldGet(){
final var data="Hello";
when(mockerService.getGrpcResponse(data)).thenReturn(new Records());
final var responseEntity=controller.getData(data);
assertEquals(responseEntity.getBody(),new Records());
}
}
responseEntity.getBody() is returning null.
Normal flow is working fine but with Junit when I am mocking the client service call, it is returning null.
I am confused why always it is returning null.
Any idea where I am getting wrong.
you have not added when then statement for service.getData(),
and below stubbing have not been called any where
when(mockerService.getGrpcResponse(data)).thenReturn(new Records());
use when then to mock service.getData() like this,
when(mockerService.getData(data)).thenReturn(new Records());
annotate this 'MyControllerTest' class with #WebMvcTest(MyController.class) and the rerun it will work, otherwise its not able to mock actual controller class.

Unable to test controller using MockMVC

I am trying to test my controller using MockMvc. While performing this mockMvc.perform(requestBuilder).andReturn(); It doesn't hit my API. So I am getting this response.
org.junit.ComparisonFailure: The Mock Response object should be same
Expected :dGVzdDEyMw==
Actual :
This is my controller class
public class AddLibClientRestController
{
#Autowired
private AddAPIService addAPIService;
#PostMapping(value = "/v1/add")
public String encrypt (#RequestParam final String plainText) throws GeneralSecurityException
{
return addAPIService.add(plainText);
}
}
This is my test class
public class AddLibClientRestControllerTest
{
/** The instance of EncryptionAPIService. */
#MockBean
private AddAPIService mockAddAPIService;
#Autowired
private MockMvc mockMvc;
#Test
public void testEncryptWithMockObjectReturned () throws Exception
{
final MockHttpServletRequestBuilder requestBuilder =
post("/v1/add")
.param("plainText", "test123");
when(mockAddAPIService.add(anyString())).thenReturn("dGVzdDEyMw==");
final MvcResult result = mockMvc.perform(requestBuilder).andReturn();
assertEquals("The Mock Response object should be same", "dGVzdDEyMw==",
result.getResponse().getContentAsString());
}
}
Please suggest something, what i am doing wrong here in this. Thanks

Spring controller test path variable gives 404

I know this question has been asked here but I can't find an answer. I have a Spring REST controller endpoint that accepts path variables but I keep getting a 404 instead of 200.
Here's my controller method:
#GetMapping("/colorNames/{colorFamily}")
public ResponseEntity<List<ColorNameFamilyDTO>> getColorNamesByColorFamily(#PathVariable String colorFamily)
{
List<ColorNameFamilyDTO> colorInformations = service.getColorNamesByColorFamily(colorFamily.toUpperCase());
return ResponseEntity.ok(colorInformations);
}
and my test is:
#RunWith(SpringRunner.class)
#WebMvcTest(InfoController.class)
public class InfoControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private InfoService service;
#Autowired
private ObjectMapper objectMapper;
#Test
public void testGetColorNamesByFamily() throws Exception
{
List<ColorNameFamilyDTO> colorInformations = new ArrayList<>();
Mockito.when(service.getColorNamesByColorFamily(Mockito.anyString()))
.thenReturn(colorInformations);
mockMvc.perform(get("/colorNames/{colorFamily}", "Blue")
.contentType("text/plain")).andExpect(status().isOk());
}
}
I've tried use param and also specifying the string in the path directly. What's going wrong? I'm using SpringBoot 2.1.3.RELEASE.
Adding a doPrint() shows up this on the console:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /colorNames/Blue
Parameters = {}
Headers = [Content-Type:"text/plain"]
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.controller.Controller
Method = public org.springframework.http.ResponseEntity<java.util.List<com.dto.ColorNameFamilyDTO>> com.controller.getColorNamesByColorFamily(java.lang.String)
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 = []
If there is no endpoint for "/colorNames", you will get HTTP 404. Therefore, check your controller. Your controller class should be marked with #RestController annotation.
You can try to use RequestBuilder object to call controller
requestBuilder = MockMvcRequestBuilders.get("/colorNames/{colorFamily}", "Blue")
.contentType(MediaType.TEXT_PLAIN_VALUE)
.accept(MediaType.APPLICATION_JSON_UTF8);
mockMvc.perform(requestBuilder)
.andExpect(status().isOk())
.andDo(print())
.andReturn();
print() will state you which api path you are calling
Update :
Please check controller and test classes
#RestController
public class AddDataController {
#Autowired
public AddDataService addDataService;
#GetMapping(value = "colourNames/{pathVar}")
public ResponseEntity dataAdded(#PathVariable String pathVar){
return addDataService.printPathVariable(pathVar);
}
}
and Test class should be
#WebMvcTest(AddDataController.class)
#RunWith(SpringRunner.class)
class AddDataControllerTest {
#MockBean
public AddDataService addDataService;
#Autowired
public MockMvc mockMvc;
#BeforeEach
public void setUp(){
MockitoAnnotations.initMocks(this);
}
#Test
void dataAdded() throws Exception {
RequestBuilder requestBuilder = MockMvcRequestBuilders.get("/colourNames/{pathVar}", "Blue")
.contentType(MediaType.TEXT_PLAIN_VALUE);
mockMvc.perform(requestBuilder)
.andExpect(status().isOk())
.andDo(print())
.andReturn();
}
}
Can you share print() response here

Spring Boot Tests- return 200 when should 404

I wrote an application with Warehouses. I have spring functions, i created Exceptions and Controller to them. Problem is when i am trying to test them. I send request as "GET" to get free space of warehouse (actualspace/100 to get %). Id of WH is -5 so i expect to get 404 not found. Instead of that in postman or in chrome i get error 500 and in intelij i get 200. Any help?
Test:
#Test
public void getFillNotExistingTest() throws Exception{
mvc.perform(MockMvcRequestBuilders
.get("/api/fulfillment/-5/fill"))
.andExpect(status().isNotFound());
}
Rest in class test:
#RunWith(SpringRunner.class)
#AutoConfigureMockMvc
#WebMvcTest(controllers = WareHouseController.class)
public class Tests {
#Autowired
private MockMvc mvc;
#Autowired
private WebApplicationContext webApplicationContext;
#MockBean
WareHouseController wareHouseController;
#Before
public void setUp() {
this.mvc = webAppContextSetup(webApplicationContext).build();
}
FullfilmentContainer is list with warehouses, each warehouse have place,id,nam etc and product list, each product list have items (name, amount etc) and each item have rating list (ratings with date, number)
Tested funcion:
#GetMapping("/api/fulfillment/{wh_id}/fill") //LP9
public ResponseEntity<Object> getPercent(#PathVariable ("wh_id") int wh_id) throws FulfillmentNotFoundException {
FulfillmentCenter ful=FulfillmentCenterContainer.searchID(wh_id);
assert ful != null;
if (ful.getPercent(ful) >= 0)
return new ResponseEntity<>(ful.getPercent(ful), HttpStatus.OK);
else
throw new FulfillmentCenterNotFoundController();
}
Funcion getPercent returns a number (its ok).
And Controller for Exception:
public class FulfillmentCenterNotFoundController extends RuntimeException {
#ResponseStatus(HttpStatus.NOT_FOUND)
#ExceptionHandler(value = FulfillmentNotFoundException.class)
public static ResponseEntity<Object> NotFoundExceptionWH(){
return new ResponseEntity<>("Fulfillment not found- error 404", HttpStatus.NOT_FOUND);
}
}
and Exception:
public class FulfillmentNotFoundException extends RuntimeException {
private static final long serialVersionUID=1L;
}
Any ideas what i done wrong?
You need to mock your call for FulfillmentCenterContainer.searchID(wh_id)
Try using below
FulfillmentCenter ful = new FulfillmentCenter();
(ful.settPercent(-5)
Mockito.when(FulfillmentCenterContainer.searchID(Mockito.eq(-5)).thenReturn(ful);

Spring boot REST: cannot test validation of #RequestParam

I want to test controller of Spring boot API with class structure as below:
Controller:
#RestController
#RequestMapping("/member-management")
#Validated
public class MemberManagementController {
private final MemberManagementService memberManagementService;
public MemberManagementController(MemberManagementService memberManagementService) {
this.memberManagementService = memberManagementService;
}
#GetMapping(value = "/view-member")
public ResponseEntity<?> viewMember(
#NotBlank(message = "username must not be blank!!")
#Size(max = 20, message = "maximum size of username id is 20!!")
#RequestParam("username") String username) {
...
}
...
Controller advice:
#ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Object> handleConstaintViolatoinException(final ConstraintViolationException ex) {
List<String> details = new ArrayList<>();
Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
for (ConstraintViolation<?> violation : violations) {
details.add(violation.getMessage());
}
ApiErrorResUtil error = new ApiErrorResUtil(String.valueOf(HttpStatus.BAD_REQUEST.value()),
"Request param error", details);
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
...
}
Unit test:
#RunWith(MockitoJUnitRunner.class)
public class MemberManagementControllerTest {
#InjectMocks
private MemberManagementController memberManagementController;
#Mock
private MemberManagementService memberManagementService;
private MockMvc mockMvc;
#Before // Execute before each test method
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(memberManagementController)
.setControllerAdvice(new CustomRestExceptionHandler()) // add ControllerAdvice to controller test
.build();
}
#Test
public void viewMember_usernameSizeExceedsMaximumLimit() throws Exception {
// Value from client
String username = "a12345678901234567890"; // 21 characters
MemberResDtoDataDummy memberResDtoDataDummy = new MemberResDtoDataDummy();
when(memberManagementService.viewMember(username)).thenReturn(memberResDtoDataDummy.getMember1());
mockMvc.perform(get("/member-management/view-member").param("username", username))
.andExpect(status().isBadRequest()).andReturn();
}
Problem:
java.lang.AssertionError: Status expected:<400> but was:<200>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
...
Could anybody help me to resolve this proplem, why expected status is 200 instead of 400, other tests of POST, PUT, PATCH, DELETE request method with invalid inputted param are still working fine :(
When you want to test your UI layer without the cost of starting a server, you have to define this test as a spring-boot one and autowired the MockMvc.
#SpringBootTest
#AutoConfigureMockMvc
This class-annotations will load all the applicationContext without server.
If you just want to load your web layer, put just this annotation on your test class.
#WebMvcTest
With this annotation Spring Boot instantiates only the web layer rather than the whole context.
In both case you have to autowired the MockMvc type.

Categories

Resources