Issue
I have an application that uses Spring MVC for running a REST service (without Spring Boot). Context is mainly loaded from the parent's one.
I have a controller and I would like to test it via MockMvc
.
I have tried to set up local test context manually, but it wasn't enough for running tests. I assume, there should be extra beans I haven't set up.
My controller is:
@RestController
public class ProrertyEditorController extends AbstractPropertyEditorController {
@Autowired
protected PropertyEditorService prorertyEditorService;
@RequestMapping(method = RequestMethod.DELETE, value = "/{dataType}/deletewithcontent")
@ResponseStatus(value = HttpStatus.OK)
public void deleteWithContent(@PathVariable("dataType") String dataType, @RequestParam("deleteall") boolean deleteAllContent, @RequestBody String node) {
try {
JSONArray itemsToDelete = new JSONArray(node);
prorertyEditorService.deleteItemsWithContent(dataType, itemsToDelete, deleteAllContent);
} catch (Exception e) {
//handling exception
}
}
}
Up to this moment, test for controller looks like this:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("classpath*:configBeans1.xml")
public class ProrertyEditorControllerTest{
private MockMvc mockMvc;
@Mock
private PropertyEditorService mockService;
@InjectMocks
private ProrertyEditorController controller;
@Before
public void setup() {
mockMvc = MockMvcBuilders.standaloneSetup(new ProrertyEditorController()).build();
}
@Test
public void deleteWithContentTest() throws Exception {
mockMvc.perform(delete("/full/path/{dataType}/deletewithcontent", type)
.param("deleteall", "true")
.param("node", "[{\"test key1\":\"test value1\"}, {\"test keys2\":\"test value2\"}]"));
verify(mockService, times(1)).deleteItemsWithContent(eq("promotion"), eq(new JSONArray("[{\"test key1\":\"test value1\"}, {\"test keys2\": \"test value2\"}]")), eq(true));
}
}
Unfortunately, it doesn't work due to Failed to load ApplicationContext
and no bean is created.
PS There is an option to use
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
However it may require refactoring of controllers method.
Solution
It turned out that it is absolutely possible to do it. There are just a few configs required to launch it.
You will need
spring-test
in yourpom.xml
:<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <scope>test</scope> </dependency>
Create a
testContext.xml
file. In my case, it was literally empty:<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
Nevertheless, it is still required, otherwise,
MockMVC
will not start since there is no context.Config your
ControllerTest
class with the following annotations:@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath*:testContextConfig.xml") @WebAppConfiguration public class ControllerTest { ... }
Without
@ContextConfiguration
theMockMVC
won't work.Create a
MockMVC
instance in@Before
method:private MockMvc mockMvc; @Mock private Service mockService; @Before public void setup() { MockitoAnnotations.initMocks(this); mockMvc = MockMvcBuilders.standaloneSetup(new Controller(mockService)) .setHandlerExceptionResolvers(exceptionResolver()) //crucial for standaloneSetup of MockMVC .build(); }
As far as I've understood,
setHandlerExceptionResolvers
is a crucial part ofmockMVC
setup.
Answered By - ryzhman
Answer Checked By - Pedro (JavaFixing Volunteer)