I am Junit testing a controller which uses a JPA repositroy for the database. My H2 in memory database is working correctly, and my GET Request mapping is working as expected. My PUT is getting a 403, while I expect a 200. I've tried a variety of different configurations using AutoConfigureMockMvc with secure false, and also excluding security auto configuration.
Is there something I am missing regarding PUT requests, the security configuration, or need to add configuration around the tokens?
Here is my Junit Test, saveTest works correctly while updateTest returns a 403.
#EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc(secure = false)
#Import(SecurityConfig.class)
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class DBcontroltest {
#Autowired
DbRequest dbRequest;
#Autowired
ConnectionRequestRepository connectionRequestRepository;
#Autowired
private MockMvc mockMvc;
private String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
private SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
private Date date;
private String dateFormatted = "2019-11-26T14:33:13.175+0000";
{
try {
date = simpleDateFormat.parse("2019-11-26T14:33:13.175+0000");
} catch (ParseException e) {
e.printStackTrace();
}
}
#Test
public void saveTest() throws Exception {
ConnectionRequest connectionRequest = new ConnectionRequest((long) 1, "bleep", "market", "dev", "conn1", "fun", "java", "styff", "hello", "whoop", date, "dldl");
connectionRequestRepository.save(connectionRequest);
String body = "{\"connectionId\":1,\"requestor\":\"bleep\",\"market\":\"market\",\"platform\":\"dev\",\"environment\":\"conn1\",\"connectionName\":\"fun\",\"connectionType\":\"java\",\"databaseId\":\"styff\",\"databasePwd\":\"hello\",\"email\":\"whoop\",\"requestDate\":\"" + dateFormatted + "\",\"jobStatus\":\"dldl\"}\n" +
" ";
mockMvc.perform(get("/api/selectDB/{connectionId}" ,1))
.andExpect(content().json(body))
.andExpect(status().isOk());
}
#Test
public void updateTest() throws Exception {
ConnectionRequest connectionRequest = new ConnectionRequest((long) 1, "bleep", "market", "dev", "conn1", "connname", "java", "db", "hello", "email#aol.com", date, "done");
connectionRequestRepository.save(connectionRequest);
String body3 = "{\"requestor\":\"NEWGUY\"}";
MockHttpServletRequestBuilder builder =
MockMvcRequestBuilders.put("/api/updateDB/{connectionId}" ,1)
.contentType("application/json")
.content(body3);
System.out.println(connectionRequestRepository.findById((long) 1));
this.mockMvc.perform(builder)
.andExpect(MockMvcResultMatchers.status()
.isOk())
.andDo(MockMvcResultHandlers.print());
System.out.println(connectionRequestRepository.findById((long) 1));
}
}
Here is my controller,
#Data
#RestController
#RequestMapping("/api/")
public class DbRequest {
#Autowired
private ConnectionRequestRepository connectionRequestRepository;
private ConnectionRequest connectionRequest;
#GetMapping("/selectDB/{connectionId}")
public ResponseEntity<ConnectionRequest> getRequestById(#PathVariable("connectionId") Long connectionId) throws Exception {
ConnectionRequest connectionRequest = connectionRequestRepository.findById(connectionId)
.orElseThrow(() -> new Exception("Connection Request " + connectionId + " not found"));
return ResponseEntity.ok().body(connectionRequest);
}
#PutMapping("/updateDB/{connectionId}")
public ResponseEntity<ConnectionRequest> updateConnectionRequest(#PathVariable("connectionId") Long connectionId,
#Valid #RequestBody ConnectionRequest connectionRequestDetails) throws Exception {
long completedDateTime = System.currentTimeMillis();
System.out.println("completeDateTime is " + completedDateTime);
ConnectionRequest connectionRequest = connectionRequestRepository.findById(connectionId)
.orElseThrow(() -> new Exception("Connection Request " + connectionId + " not found"));
System.out.println("value for connectionrequest is " + connectionRequest);
System.out.println("value for connectionrequestdetails is " + connectionRequestDetails);
connectionRequest.setRequestor(connectionRequestDetails.getRequestor());
final ConnectionRequest updatedConnectionRequest = connectionRequestRepository.save(connectionRequest);
return ResponseEntity.ok(updatedConnectionRequest);
}
}
This is the output from running the junit test, with good data. I've tested the application, and it's working as expected, only Junit fails.
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /api/updateDB/1
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8"]
Body = {"requestor":"NEWGUY"}
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken#80b6098}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 403
Error message = Forbidden
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :403
<Click to see difference>
By using csrf I was able to get this working correctly.
MockHttpServletRequestBuilder builder =
put("/api/updateDB/{connectionId}", 1)
.contentType("application/json")
.content(body3)
.contentType(MediaType.APPLICATION_JSON)
.with(csrf());
System.out.println(connectionRequestRepository.findById((long) 1));
this.mockMvc.perform(builder)
.andExpect(content().json(body))
.andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print());
System.out.println(connectionRequestRepository.findById((long) 1));
Create the below for test profile.
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(jsr250Enabled = true)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root").password("system").roles("SYSTEM");
}
}
Inside your test class,
public class DBcontroltest {
...
#Test
#WithUserDetails(value = "root")
public void updateTest() throws Exception {
...
}
Please visit this project on github, I have setup spring boot testing using spring-security using spring boot.
Test case: https://github.com/reflexdemon/shop/blob/master/src/test/java/org/shop/service/CatalogServiceTest.java
Config: https://github.com/reflexdemon/shop/blob/master/src/main/java/org/shop/WebSecurityConfig.java
Related
Controller:
#ApiOperation(value = " update record", response = APIResponse.class)
#ApiResponses(value = {#ApiResponse(code =200, message = "OK"),
#ApiResponses(value = {#ApiResponse(code =500, message = "Internal server error"),
#ApiResponses(value = {#ApiResponse(code =404, message = "NO_RECORD")})
#PutMapping(value = "/update/{id}")
#ResponseBody
public ResponseEntity<APIResponse> updateRecord(HttpServletRequest request, #RequestBody RecordDTO input, #PathVariable(value="id") int code){
APIResponse response = null;
try{
response = service.updateRecord(code, input);
}
catch(JSONException e){
log.error("Error Parsing JSON");
response = new APIResponse(HttpStatus.INTERNAL_SERVER_ERROR, ERROR_JSON_PARSING, ERROR);
}
return new ResponseEntity<>(response, HttpStatus.OK);
}
my test case foor controller:
#Test
public void update() throws Exception{
RecordDTO recordDto = new RecordDTO();
Object mapper = new ObjectMapper();
String value = mapper.writeValueAsString(StationDTO);
given(service.updateRecord(anyInt(), any(RecordDTO.class))).willThrow(JSONException.class);
mockMvc.perform(put(baseUrl + "/update/12")
.contentType(MediaType.APPLICATION_JSON).content(value))
.andExpect(status().isInternalservererror())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.status",Matchers.is("INTERNAL_SERVER_ERROR")))
.andExpect(jsonPath("$.message",Matchers.is("ERROR_JSON_PARSING")))
.andExpect(jsonPath("$.resposeStatus",Matchers.is("ERROR")));
APIResponse response = new APIResponse(HttpStatus.OK, SUCCESS, SUCCESS, null);
given(service.updateRecord(anyInt(), any(RecordDTO.class))).willReturn(response);
mockMvc.perform(put(baseUrl + "/update/12")
.contentType(MediaType.APPLICATION_JSON).content(value))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.status",Matchers.is("OK")))
.andExpect(jsonPath("$.message",Matchers.is("SUCCESS")))
.andExpect(jsonPath("$.resposeStatus",Matchers.is("SUCCESS")));
}
DTO:
public class RecordDTO{
private String id;
private String name;
private String number;
}
I am getting java.lang assertion error expected 500 but was 200. I don't what is wrong with the test case.. Is there any other way to write the test case? Also can you recommend any platform from where i can gain knowledge of how to write test cases then do comment down. Thanks for the help!
Seems like your mocked service is not injecting into your controller.
Alternative solution (I assume you use Spring-Boot):
DisableAutowireRequireInitializer. This will prevent to load all dependencies inside your Controller.
Create inside your ControllerTest inner class: private static ServiceImplMock entends ServiceImpl
Now, override updateRecord method inside ServiceMock to do your testing cases
#Override
public APIResponse updateRecord(int code, RecordDTO input) throws JSONException {
if(code == 12) throw new JSONException(...)
else your_business_logic
}
Now, add this ServiceImplMock into your #SpringBootTest
#SpringBootTest(classes = {
Controller.class,
ControllerTest.ServiceImplMock.class,
...
})
#AutoConfigureMockMvc
#ContextConfiguration( initializers = {DisableAutowireRequireInitializer.class })
class ControllerTest {
Now, your test cases should work (Remove given(...).willThrow(...); since we don't need it anymore)
Also can you recommend any platform from where i can gain knowledge of how to write test cases then do comment down
https://www.baeldung.com/junit
https://www.baeldung.com/spring-boot-testing
https://mkyong.com/spring-boot/spring-boot-junit-5-mockito/
i have a problem testing an endpoint which use #ModelAttribute I don't know very well how to test with this annotation and the test response is java.lang.AssertionError: Content type not set , here is the controller method:
#PostMapping
public ResponseEntity<?> createTestimonials(#ModelAttribute(name = "testimonialsCreationDto") #Valid TestimonialsCreationDto testimonialsCreationDto) {
try {
return ResponseEntity.status(HttpStatus.CREATED).body(iTestimonials.createTestimonials(testimonialsCreationDto));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.CONFLICT).body(e.getMessage());
}
}
Here is the test:
#Test
void createTestimonials() throws Exception {
//Given
String name = "Testimonio 159";
String contentTestimonial = name + " content!";
TestimonialsCreationDto testimonialsCreationDto = new TestimonialsCreationDto();
testimonialsCreationDto.setName(name);
testimonialsCreationDto.setContent(contentTestimonial);
//When
mockMvc.perform(post("/testimonials")
.flashAttr("testimonialsCreationDto", testimonialsCreationDto)
.contentType(MediaType.MULTIPART_FORM_DATA)
.content(objectMapper.writeValueAsString(testimonialsCreationDto))
.characterEncoding("UTF-8"))
//Then
.andExpect(status().isCreated())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.name", is(name)))
.andExpect(jsonPath("$.content", is(contentTestimonial)));
verify(testimonialsService).createTestimonials(any());
}
MockHttpServletRequest:
HTTP Method = POST
Request URI = /testimonials
Parameters = {}
Headers = [Content-Type:"multipart/form-data;charset=UTF-8", Content-Length:"74"]
Body = {"name":"Testimonio 159","image":null,"content":"Testimonio 159 content!"}
Session Attrs = {}
MockHttpServletResponse:
Status = 200 ---> IDK why response with 200 code
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Content type not set
You have to add path value to PostMapping :
#PostMapping(path = "/testimonials", produces = MediaType.MULTIPART_FORM_DATA)
I'm trying to test my microservice endpoint Get Payees using MockMvc to perform the get request.
I've already set the behavior with mockito.when(), so whatever ID used in the request, it should return my response.
I have this test:
#ControllerTest
#AutoConfigureMockMvc
public class PayeesApiControllerGetPayeesTest {
private static final String ACCOUNTS_URI = "/payees";
#Autowired
private MockMvc mvc;
#Autowired
private GetPayeesModule module;
#Test
public void testGetPayees() throws Exception {
when(module.execute(
anyString(),
anyInt(),
anyInt(),
anyString(),
anyString(),
anyString(),
anyString(),
anyString(),
anyString()))
.thenReturn(
ResponseEntity.ok()
.header(X_V_HEADER, X_V_VERSION)
.header(X_FAPI_INTERACTION_ID_HEADER, UUID.randomUUID().toString())
.body(
new ResponsePayee()
.data(
new PayeeData()
.addPayeesItem(
new PayeeDetails()
.id(35L)
.type(PayeeType.DOMESTIC)
.fullName("Robert Doe")
.description("My brother")
.bsb("010-147")
.accountNumber("123456789")))));
mvc.perform(
get(ACCOUNTS_URI)
.param("userId", "1")
.accept(MediaType.APPLICATION_JSON)
.header(X_V_HEADER, X_V_VERSION)
.with(jwtWithAccountsBasicReadPermissionAndBankClientRole()))
.andExpect(status().isOk())
.andExpect(content().string("DOMESTIC"));
}
And this is my Controller:
#Controller
#Validated
#RequiredArgsConstructor
public class PayeesApiController implements PayeesApiInterface {
private final GetPayeesModule getPayeesModule;
private final CreatePayeesModule createPayeesModule;
#Override
public ResponseEntity<ResponsePayee> getPayees(
String userId,
Integer page,
Integer pageSize,
String xRequestId,
String xCorrelationContext,
String xCorrelationId,
String xFapiAuthDate,
String xFapiCustomerIpAddress,
String xCdsClientHeaders) {
return getPayeesModule.execute(
userId,
page,
pageSize,
xRequestId,
xCorrelationContext,
xCorrelationId,
xFapiAuthDate,
xFapiCustomerIpAddress,
xCdsClientHeaders);
}
#Controller annotation:
/**
* Meta-annotation (annotation of annotations) to group Spring's annotations for testing web slice.
*/
#WebMvcTest()
#ActiveProfiles("test")
#Import(ControllerTestConfiguration.class)
#Retention(RetentionPolicy.RUNTIME)
public #interface ControllerTest {}
This is what my console shows:
2021-01-26 18:56:58.010 INFO 17428 --- [ main] c.m.s.o.HttpServletLogService : REQUEST m:[GET], p:[/payees], q:[null], h:[{empty}], b:[{empty}]
MockHttpServletRequest:
HTTP Method = GET
Request URI = /payees
Parameters = {userId=[1]}
Headers = [Accept:"application/json", x-v:"1"]
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.marlo.payees.api.PayeesApiController
Method = com.marlo.payees.api.PayeesApiController#getPayees(String, Integer, Integer, String, String, String, String, String, 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 = 200
Error message = null
Headers = [X-Correlation-Id:"f7d29ced-1ddc-4788-93fb-ba6655da412d", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
------EDIT--------
Adding the ApiInterface example on how I use RequestMapping
#RequestMapping(
value = "/payees",
produces = {"application/json"},
method = RequestMethod.GET)
default ResponseEntity<ResponsePayee> getPayees
For some reason, I always get empty body even with 200 status code.
If you guys could help me... i would appreciate it.
Thanks in advance.
If I understood well, your
private GetPayeesModule module;
in
public class PayeesApiControllerGetPayeesTest {
should be annotated with
#MockBean
and not with
#Autowired
I have one simple test to write for a POST method in a RestController. This post mapping works fine when i run the application. But, in it's test i always get HttpMessageNotReadableException with 400-Bad Request.
InternalCustomerController.class
#RestController
#RequestMapping(
value = "/",
consumes = {MediaType.APPLICATION_XML_VALUE},
produces = {MediaType.APPLICATION_XML_VALUE})
#RequiredArgsConstructor
public class InternalCustomerController {
private final CustomerService customerService;
#PostMapping(value = "/cpdupdate")
public Notification updateCustomerProduct(#NotNull #RequestBody Customer customer) {
return customerService.handleUpdateCustomerProduct(customer);
}
}
InternalCustomerControllerTest.class
#RunWith(SpringRunner.class)
#WebMvcTest(controllers = InternalCustomerController.class)
#Import(TestObjectMapperConfig.class)
public class InternalCustomerControllerTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private CustomerService customerService;
#Test
public void testUpdateCustomerProduct() throws Exception {
Customer validCustomer = createValidCustomer("76d211bb680843c5b63afa1c13a0a5e5", "60");
when(this.customerService.handleUpdateCustomerProduct(any()))
.thenReturn(buildDummyNotification(messageId, "SUCCESS"));
mockMvc.perform(post("/cpdupdate")
.contentType(MediaType.APPLICATION_XML)
.content(objectToString(validCustomer)))
.andExpect(status().isOk()); // Fails Here as it gets 400 in return
}
// Customer Class Generated from Provided XSD on maven build
private static Customer createValidCustomer(String internalProductId, int customerId) {
Customer customer = new Customer();
customer.setCustomerId(customerId);
Customer.InternalProducts products = new Customer.InternalProducts();
products.getProductIds().add(internalProductId);
customer.setInternalProducts(products);
return customer;
}
private Notification buildDummyNotification(String messageId, String message) {
return Notification.builder()
.messageId(messageId)
.message(message)
.build();
}
private static String objectToString(Object element) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
JAXBContext context = JAXBContext.newInstance(element.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(element, outputStream);
return outputStream.toString("UTF-8");
} catch (JAXBException | IOException ex) {
log.error(ex.getMessage(), ex);
return "";
}
}
}
Error message contains JSON parse error: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token. So i tried adding a configuration for ObjectMapper and Import it into the test.
#Configuration
public class TestObjectMapperConfig {
#Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
return objectMapper;
}
}
But i still get the error.
What i am missing here?
Full Error Message
Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
at [Source: java.io.PushbackInputStream#53311681; line: 4, column: 49] (through reference chain: com.clps.Customer["internalProducts"]->com.clps.Customer$InternalProducts["productId"])]
MockHttpServletRequest:
HTTP Method = POST
Request URI = /cpdupdate
Parameters = {}
Headers = {Content-Type=[application/xml]}
Handler:
Type = com.pt.controllers.InternalCustomerController
Method = public com.pt.models.Notification com.pt.controllers.InternalCustomerController.updateCustomerProduct(com.clps.Customer)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotReadableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
java.lang.AssertionError: Status
Expected :200
Actual :400
I have a Rest controller similar to this one:
#RestController
public class UserRestController {
#Autowired
private UserService userService;
#RequestMapping(value = "/user/activate", method = RequestMethod.POST)
public ResponseEntity<UserDTO> activate(
#RequestParam(required = true) final String email,
#RequestParam(required = true) final String key) {
UserDTO userDTO = userService.activateAccount(email, key);
return new ResponseEntity<UserDTO>(userDTO, HttpStatus.OK);
}
}
When I invoke it using Postman and I don't send the 'key' parameter, I receive this JSON message:
{
"timestamp": 1446211575193,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MissingServletRequestParameterException",
"message": "Required String parameter 'key' is not present",
"path": "/user/activate"
}
On the other hand, I am testing this method with JUnit and the MockMVC Spring utility.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = ApplicationConfig.class)
#WebAppConfiguration
public class UserRestControllerTest {
private static MockMvc mockMvc;
#Mock
private UserService userService;
#InjectMocks
private UserRestController userRestController;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders
.standaloneSetup(userRestController)
.setMessageConverters(
new MappingJackson2HttpMessageConverter(),
new Jaxb2RootElementHttpMessageConverter()).build();
}
#Test
public void testActivateRequiredParams() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders.post("/user/activate")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().isBadRequest())
.andExpect(
MockMvcResultMatchers.content().contentType(
UtilsUnitTest.APPLICATION_JSON_UTF8))
.andExpect(
jsonPath(
"message",
is("Required String parameter 'email' is not present")));
}
}
But when I execute this test I notice that the response is not a JSON message. In fact, I get an exception:
java.lang.AssertionError: Content type not set
Particularly, the completed result is
MockHttpServletRequest:
HTTP Method = POST
Request URI = /user/activate
Parameters = {}
Headers = {Content-Type=[application/x-www-form-urlencoded]}
Handler:
Type = com.company.controller.UserRestController
Method = public org.springframework.http.ResponseEntity<com.company.dto.UserDTO> com.company.controller.UserRestController.activate(java.lang.String,java.lang.String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.bind.MissingServletRequestParameterException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 400
Error message = Required String parameter 'email' is not present
Headers = {}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
I deduce that when an exception is thrown this is not converted to JSON format (I get a correct JSON result when I send the email and key parameters)
The question is obvious: what should I change in the Unit Test configuration to get a JSON error message in case of an exception be thrown?
The problem is that the test stops after following assertion fails:
.andExpect(MockMvcResultMatchers.content().contentType(UtilsUnitTest.APPLICATION_JSON_UTF8))
Beside this, jsonPath("message"... won't hit anything. To validate the returned error message use MockMvcResultMatchers.status().reason(<ResultMatcher>).
The following test should do the job:
#Test
public void testActivateRequiredParams() throws Exception {
final ResultActions result = mockMvc
.perform(MockMvcRequestBuilders.post("/user/activate")
.contentType(MediaType.APPLICATION_FORM_URLENCODED).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultHandlers.print());
result.andExpect(MockMvcResultMatchers.status().isBadRequest());
result.andExpect(MockMvcResultMatchers.status().reason(is("Required String parameter 'email' is not present")));
}
But think about if this (testing for error messages) is a good idea in general, maybe see this discussion.