0

I have created an rest api and tested via postman and able to get success response as expected. Now i have created Junit test case for the above api but while executing getting "java.lang.AssertionError: Status expected:<200> but was:<415> ". Not able to figure out why this exception is happening.

I'm new to both Mockito and MockMVC so any help would be appreciated.

Below is my test class

package com.example.demo.hystricks;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.io.Serializable;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

import org.apache.commons.lang.SerializationUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.RequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.example.demo.DemoController;
import com.example.demo.DemoService;
import com.example.demo.InputModel;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = DemoController.class)
public class DemoControllerTest {

private MockMvc mockMvc;

@InjectMocks
private DemoController demoController;

@MockBean
private DemoService demoService;

@MockBean
private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;

@Before
public void setUp() {

    MockitoAnnotations.initMocks(this);
    DemoController demoController = new DemoController(demoService);
    this.mockMvc = MockMvcBuilders
            .standaloneSetup(demoController).
            setMessageConverters(mappingJackson2HttpMessageConverter).build();

}

@Test
public void postData() throws Exception {

    InputModel inputModel = new InputModel("12345","Test","CSC",getEventTime());
    System.out.println("before api....");
    RequestBuilder requestBuilder  = MockMvcRequestBuilders.post("/demoService")
            .accept(MediaType.APPLICATION_JSON)
            .content(inputModel.toString())
            .contentType(MediaType.APPLICATION_JSON);
    mockMvc.perform(requestBuilder)
    .andDo(MockMvcResultHandlers.print())
    .andExpect(status().isOk());
    System.out.println("after api....");
}

private LocalDateTime getEventTime() {

    Instant instant = Instant.ofEpochMilli(Instant.now().toEpochMilli());
    LocalDateTime eventTimestamp = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    return eventTimestamp;
}

}

My Rest Controller

@RestController
public class DemoController {

private static final Logger LOGGER = LoggerFactory.getLogger(DemoController.class);

public final DemoService demoService;

public DemoController(DemoService demoService) {
    this.demoService = demoService;
}

@RequestMapping(value = "demoService",method = RequestMethod.POST)
public ResponseEntity<String> postData(
        @RequestBody InputModel inputModel){

    LOGGER.info("DemoService Entered successfully");
    demoService.postData(inputModel.getId(),inputModel.getName(),
            inputModel.getDepartment(), inputModel.getJoinDate());
    LOGGER.info("DemoService Exited successfully");
    return new ResponseEntity<String>("success",HttpStatus.OK) ;
}

}

Console Message before api:

>2018-10-16 12:15:49.391  WARN 6200 --- [           main] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json' not supported]
2018-10-16 12:15:49.437  INFO 6200 --- [       Thread-3] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@5023bb8b: startup date [Tue Oct 16 12:15:48 IST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@76a4ebf2

Failure Stack Trace:

>java.lang.AssertionError: Status expected:<200> but was:<415>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:55)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:82)
at org.springframework.test.web.servlet.result.StatusResultMatchers.lambda$matcher$9(StatusResultMatchers.java:619)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:178)
at com.example.demo.hystricks.DemoControllerTest.postData(DemoControllerTest.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
1
  • 2
    Your test is wrong. Remove your @Before method, spring does all of that for you. Remove the DemoController and MappingJackson2HttpMessageConverter fields from the test and add @AUtowired to your MockMvc field. You want a web slice test but are working hard around the framework. Finally I doubt that inputModel.toString() will create a valid JSON body. Commented Oct 16, 2018 at 7:34

1 Answer 1

1

The issue is on this line:

 @MockBean
 private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;

You are mocking this converter. Create a instance using new instead:

this.mockMvc = MockMvcBuilders
        .standaloneSetup(controller).
        setMessageConverters(new MappingJackson2HttpMessageConverter()).build();

Or as rightly mentioned by M. Dienum, you can do away with the below 2 lines from setUp() method and it'll work:

DemoController demoController = new DemoController(demoService);
this.mockMvc = MockMvcBuilders
        .standaloneSetup(demoController).
        setMessageConverters(mappingJackson2HttpMessageConverter).build();

After doing all this if you run into 400 error then your toString() method isn't producing valid json.

Sign up to request clarification or add additional context in comments.

2 Comments

I have removed @MockBean private MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter; and created new instance instead. It worked. Thanks M.Dienum and Aditya
Thank you so much!, I was trying to find a way to restrict the spring boot context by specifying the classes that I wanted to use to test, but the moment I did that, some autoconfiguration was missed for MockMvc, I did what you mentioned about creating a new instance of the mapping jackson and adding it and it worked like a charm!!! ``` this.mockMvc = MockMvcBuilders .standaloneSetup(controller). setMessageConverters(new MappingJackson2HttpMessageConverter()).build(); ```

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.