AssertionError when JUnit testing a JSON response - java

I am creating my first unit test, and just wanted to create something pretty simple based on one of the Spring tutorials.
Here is the error I am getting:
java.lang.AssertionError: Response content
Expected: (null or an empty string)
but: was "Debug"
My Controller:
#RestController
#RequestMapping(value = "/person")
public class PersonController {
#Autowired
protected PersonService personService;
#RequestMapping(value = "/lastName", produces = "application/json")
public String lastName(#RequestParam(value = "cid") String cid)
{
return personService.findByCId(cid).getLastName();
}
My Test:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class MvcLastNameTest {
#Autowired
private MockMvc mockMvc;
#Test
public void shouldReturnNonNullString() throws Exception {
this.mockMvc.perform(get("/person/lastName?cid=123456")).andDo(print()).andExpect(status().isOk())
.andExpect(content().string(isEmptyOrNullString()));
}
}

in your test your are expecting EmptyOrNullString, but your controller produces a lastName
change your expectation:
.andExpect(content().string("Debug")); // or any other valid lastName

Related

During unit test of Restcontroller my Mocking class does not work

I need to test one method in RestController, with mock class. But java does not understand, then its mock class and try invoke it. However, such method with the same mock class works sucsesfuly.
My RestController:
#RestController
public class OrderController {
#Autowired
ServiceOrder serviceOrder;
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "/orders", method= RequestMethod.POST, produces={"application/json; charset=UTF-8"})
public List<Order> sortOrders(#RequestParam("field") String field) {
return serviceOrder.sortOrders(field);
#PreAuthorize("hasRole('ROLE_ADMIN')")
#RequestMapping(value = "/orders/completed/period", method= RequestMethod.POST, produces={"application/json"})
public long showCompletedOrdersInPer(
#RequestParam (value = "start") String startDate,
#RequestParam (value = "end") String endDate) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate start = LocalDate.parse(startDate, formatter);
LocalDate end = LocalDate.parse(endDate, formatter);
return serviceOrder.completedOrdersInPeriod(start, end);
}
Well, test for method sortOrders() is OK, but test for showCompletedOrdersInPer() is failed.
My test class:
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {ControllersTestConfig.class})
#WebAppConfiguration
public class OrderControllerTest {
#Autowired
private WebApplicationContext webApplicationContext;
#Autowired
OrderController orderController;
#Autowired
ServiceOrder serviceOrder;
private MockMvc mockMvc;
#BeforeEach
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build();
}
// Test from method OrderController.sortOrders
// Description: we should get response.status OK
#Test
public void sortOrdersTest() throws Exception {
Mockito.when(serviceOrder.sortOrders(any())).thenReturn(null);
mockMvc.perform(MockMvcRequestBuilders.post("/orders?field=1")).andExpect(MockMvcResultMatchers.status().isOk());
}
// Test from method OrderController.showCompletedOrdersInPer
// Description: we should get response.status OK
#Test
public void showCompletedOrdersInPerTest() throws Exception {
Mockito.when(serviceOrder.completedOrdersInPeriod(any(), any())).thenReturn(1L);
mockMvc.perform(MockMvcRequestBuilders.post("/orders/completed/period?start=2020-01-01&end=2022-01-01")).andExpect(MockMvcResultMatchers.status().isOk());
}
And this is configClass:
public class ControllersTestConfig {
#Bean
public ServiceOrder serviceOrder() {
return Mockito.mock(ServiceOrder.class);
}
#Bean
public OrderController orderController(){
return new OrderController();
}
}
When i run sortOrdersTest(), test is ok, when i run showCompletedOrdersInPerTest(), i have
Status expected:<200> but was:<500>
Expected :200
Actual :500
If i run tests with debug, i see, then in sortOrders() mock works and serviceOrder.sortOrders(field) does not invoke, and in showCompletedOrdersInPer() mock does not work and java try invoke serviceOrder.completedOrdersInPeriod(start, end) and i have status 500.
Please, help me!
Well, it was a problem with parsing Integer to Long in dao layer. I resolve it and test is done.

Getting assertion error while performing test on mockmvc

I am getting assertion error saying it's getting 406 and expected 200. Not sure how to fix this. For your info i am trying to upgrade spring boot 1.5.2 to 2.1.4
Below is my code -
#ContextConfiguration(classes = ChangeController.class)
#WebAppConfiguration
public class ChangeControllerTest extends AbstractJUnit4SpringContextTests {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
}
#Test
public void verifyInvalidToDoArgument() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/log").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(print());
}
}
Controller class
#Controller
#RequestMapping("/log")
public class ChangeController {
#ApiIgnore
#RequestMapping(method = RequestMethod.GET, produces = {"text/plain"})
public
#ResponseBody
String generate() {
return "some string is here
";
}
}
Below is console response-
java.lang.AssertionError: Status
Expected :200
Actual :406

MockMvc REST controller - always returns empty body

I would like to test my REST controller using MockMvc but I always get an empty body response.
My AccountControllerUnitTest looks like this:
#RunWith(SpringRunner.class)
#WebMvcTest(AccountRestController.class)
public class AccountRestControllerUnitTests {
#Autowired
private MockMvc mockMvc;
#MockBean(name = "dtoUtil")
private DtoUtil dtoUtil;
#MockBean
private AccountService accountService;
#Test
public void canRetrieveAll() throws Exception {
when(accountService.findAll())
.thenReturn(Collections.singletonList(AccountTestFixture.createAccount()));
this.mockMvc.perform(get("/accounts")).andDo(print())
.andExpect(status().isOk());
}}
The accountService when mock works as expected, calling accountService.findAll() returns a list with a single account element.
With my used AccountRestController being:
#RestController
#AllArgsConstructor
#RequestMapping("/accounts")
public class AccountRestController {
private AccountService accountService;
#Qualifier(dtoUtil)
private DtoUtil dtoUtil;
#GetMapping
public List<AccountDto> getAccounts() {
return accountService.findAll().stream()
.map(dtoUtil::mapToDto)
.collect(Collectors.toList());
}
Running the test will result in a MockHttpServletResponse with a body that is null.
It works flawlessly for my normal (non-rest that has a model) controller, the only difference being that it doesn't use the DtoUtil.
Could that be the reason for it constantly returning null?
edit:
The DtoUtil:
#Component
public class DtoUtil{
#Autowired
private ModelMapper mapper;
public AccountDto mapToDto(Account account) {
return modelMapper.map(account, AccountDto.class);
}
}
Add to your test
when(dtoUtil.mapToDto(...)).thenCallRealMethod();

spring boot controller test, mockMov doesn't mock

I use Spring MVC and Spring boot to write a Restful service. This code works fine through postman.While when I do the unit test for the controller to accept a post request, the mocked myService will always initialize itself instead of return a mocked value defined by when...thenReturn... I use verify(MyService,times(1)).executeRule(any(MyRule.class)); and it shows the mock is not used.
I also tried to use standaloneSetup for mockMoc, but it complains it can't find the mapping for the path "/api/rule".
Could anybody help to figure out the problem?
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class MyControllerTest {
#Mock
private MyService myService;
#InjectMocks
private MyController myRulesController;
private MockMvc mockMvc;
#Autowired
private WebApplicationContext wac;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void controllerTest() throws Exception{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
Long userId=(long)12345;
MyRule happyRule = MyRule.createHappyRule(......);
List<myEvent> mockEvents=new ArrayList<myEvent>();
myEvents.add(new MyEvent(......));
when(myService.executeRule(any(MyRule.class))).thenReturn(mockEvents);
String requestBody = ow.writeValueAsString(happyRule);
MvcResult result = mockMvc.perform(post("/api/rule").contentType(MediaType.APPLICATION_JSON)
.content(requestBody))
.andExpect(status().isOk())
.andExpect(
content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
verify(MyService,times(1)).executeRule(any(MyRule.class));
String jsonString = result.getResponse().getContentAsString();
}
}
Below is my controller class, where MyService is a interface. And I have implemented this interface.
#RestController
#RequestMapping("/api/rule")
public class MyController {
#Autowired
private MyService myService;
#RequestMapping(method = RequestMethod.POST,consumes = "application/json",produces = "application/json")
public List<MyEvent> eventsForRule(#RequestBody MyRule myRule) {
return myService.executeRule(myRule);
}
}
Is api your context root of the application? If so remove the context root from the request URI and test. Passing the context root will throw a 404. If you intend to pass the context root then please refer the below test case. Hope this helps.
#RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {
#InjectMocks
private MyController myRulesController;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = standaloneSetup(myRulesController).build();
}
#Test
public void controllerTest() throws Exception{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
MyController.User user = new MyController.User("test-user");
ow.writeValueAsString(user);
MvcResult result = mockMvc.perform(post("/api/rule").contentType(MediaType.APPLICATION_JSON).contextPath("/api")
.content(ow.writeValueAsString(user)))
.andExpect(status().isOk())
.andExpect(
content().contentType(MediaType.APPLICATION_JSON))
.andReturn();
}
}
Below is the controller
/**
* Created by schinta6 on 4/26/16.
*/
#RestController
#RequestMapping("/api/rule")
public class MyController {
#RequestMapping(method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public User eventsForRule(#RequestBody User payload) {
return new User("Test-user");
}
public static class User {
private String name;
public User(String name){
this.name = name;
}
}
}

SpringBoot and REST-assured, getting 406 when 404 is thrown

In this answer, I was using REST-assured to test a post action of a file. The controller was:
#RestController
#RequestMapping("file-upload")
public class MyRESTController {
#Autowired
private AService aService;
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
#ResponseStatus(HttpStatus.CREATED)
public void fileUpload(
#RequestParam(value = "file", required = true) final MultipartFile file,
#RequestParam(value = "something", required = true) final String something) {
aService.doSomethingOnDBWith(file, value);
}
}
The controller was tested as in this answer.
Now I have an exception:
#ResponseStatus(value=HttpStatus.NOT_FOUND)
public class XNotFoundException extends RuntimeException {
public XNotFoundException(final String message) {
super(message);
}
}
and I test the case when the service throws that exception as follows:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
#WebAppConfiguration
#IntegrationTest({"server.port:0"})
public class ControllerTest{
{
System.setProperty("spring.profiles.active", "unit-test");
}
#Autowired
#Spy
AService aService;
#Autowired
#InjectMocks
MyRESTController controller;
#Value("${local.server.port}")
int port;
#Before public void setUp(){
RestAssured.port = port;
MockitoAnnotations.initMocks(this);
}
#Test
public void testFileUpload() throws Exception{
final File file = getFileFromResource(fileName);
doThrow(new XNotFoundException("Keep calm, is a test")).when(aService)
.doSomethingOnDBWith(any(MultipartFile.class), any(String.class));
given()
.multiPart("file", file)
.multiPart("something", ":(")
.when().post("/file-upload")
.then().(HttpStatus.NOT_FOUND.value());
}
}
But when I run the test I obtain:
java.lang.AssertionError: Expected status code <404> doesn't match actual status code <406>.
How can I solve this?
You may need to set the content-type header to "multipart/form-data". For example:
given()
.contentType(MediaType.MULTIPART_FORM_DATA_VALUE)
.multiPart("file", file)
.multiPart("something", ":(")
.when().post("/file-upload")
.then()...;
If that doesn't work you can try specify it for the individual multiparts:
given()
.multiPart("file", file, MediaType.MULTIPART_FORM_DATA_VALUE)
.multiPart("something", ":(", MediaType.MULTIPART_FORM_DATA_VALUE)
.when().post("/file-upload")
.then()...;

Categories

Resources