3

Most of the times instead of adding comments in an ordinary JUnit assertion, we add a message to the assertion, to explain why this is assertion is where it is:

Person p1 = new Person("Bob");
Person p2 = new Person("Bob");
assertEquals(p1, p2, "Persons with the same name should be equal.");

Now, when it comes to end point testing in a Spring Boot web environment I end up with this:

// Bad request because body not posted
mockMvc.perform(post("/postregistration")).andExpect(status().isBadRequest());

// Body posted, it should return OK
mockMvc.perform(post("/postregistration").content(toJson(registrationDto))
        .andExpect(status().isOk()));

Is there a way to get rid of the comments and add a message to this kind of assertion? So, when the test fails I will see the message.

George Z.
  • 6,643
  • 4
  • 27
  • 47
  • One idea would be to call the test method like failIfNoBodyPosted, so when the test fail you know why. – Marc Jul 09 '20 at 09:27
  • @marc hmm, yes, I have think of that before but I dislike it. Testing a controller with 10 endpoints where each endpoint has 5-6 test cases, I will end up with 60 methods with similar names, and I won't be able to know which method refers to which end point testing. Personally, when it comes to (simple) endpoint test cases, a script-like code is my taste. – George Z. Jul 09 '20 at 09:33

2 Answers2

1

I figured out that assertDoesNotThrow responds hence improves the situation (according to what I ask):

assertDoesNotThrow(() -> {
    mockMvc.perform(post("/postregistration")).andExpect(status().isBadRequest());
}, "Bad Request expected since body not posted.");
George Z.
  • 6,643
  • 4
  • 27
  • 47
  • I will not mark my answer as accepted, in case someone has something better (a less-code approach) or `MockMvc` has a built-in something for this that I do not know about. – George Z. Jul 09 '20 at 09:44
  • This might not be flexible enough in the moment you chain more ```.andExpect()``` clauses. – Marc Jul 09 '20 at 11:41
1

You can provide a custom ResultMatcher:

mockMvc.perform(post("/postregistration")
        .content(toJson(registrationDto))
        .andExpect(result -> assertEquals("Body posted, it should return OK", HttpStatus.OK.value() , result.getResponse().getStatus())))

mockMvc.perform(post("/postregistration"))
       .andExpect(result -> assertEquals("Bad request because body not posted", HttpStatus.BAD_REQUEST.value(), result.getResponse().getStatus()));

Explaination:

As of today the method .andExpect() accepts only one ResultMatcher. When you use .andExpect(status().isOk()) the class StatusResultMatchers will create a ResultMatcher in this way:

public class StatusResultMatchers {
    //...
    public ResultMatcher isOk() {
        return matcher(HttpStatus.OK);
    }
    //...
    private ResultMatcher matcher(HttpStatus status) {
        return result -> assertEquals("Status", status.value(), result.getResponse().getStatus());
    }
}

As you can see the message is hard-coded to "Status" and there is no other built in method to configure it. So even though providing a custom ResultMatcher is a bit verbose, at the moment might be the only feasible way using mockMvc.

Marc
  • 2,738
  • 1
  • 17
  • 21