Unit Testing Spring MVC JSON data-binding with JUnit and Mockito

In this post, I’ll show you how to write clean and easy to understand JUnit test for any Spring Controller that has JSON databinding through the @RequestBody annotation with only JUnit and Mockito.

My motivation for writing this post is to actually learn how to write clean unit tests of Spring Controllers with JSON databinding without the Spring Test Framework. Using only JUnit and Mockito you will never have to load a bunch of crap that you often need to when using the SpringJUnit4ClassRunner accompanied with annotations such as @ContextConfiguration. For simple unit tests you will usually never need anything other than JUnit and Mockito, as opposite to the Spring Test Framework which often comes very handy when writing integration tests.

In the following example I’ll create

– a domain object for storing information about a person
– a Spring controller that transforms a JSON string into a Person object
– a service for persisting the person
– a JUnit test to test the JSON databinding.

To get started, you will need the following Maven dependencies:

<dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.10</version>
 <scope>test</scope>
</dependency>

<dependency>
 <groupId>org.mockito</groupId></pre>
 <artifactId>mockito-all</artifactId>
 <version>1.9.0</version>
 <scope>test</scope>
</dependency>

<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-annotations</artifactId>
 <version>2.2.3</version>
</dependency>

<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-core</artifactId>
 <version>2.2.3</version>
</dependency>
<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>2.2.3</version>
</dependency>

Here is the Person.java class:


@JsonIgnoreProperties(ignoreUnknown = true)
public class Person {

private int id;

private String name;

private String username;

private String email;

// getters and setters

}

And here is the Spring Controller and the Service. I have put the service inside the Controller for simplicity, but this can  replaced with any kind of Spring container managed bean.


@Controller
public class PersonController {

 @Autowired
 private PersonService personService;

 @RequestMapping(value = "/admin/persons/add", method = RequestMethod.POST)
 public ResponseEntity<String> addPerson(@RequestBody Person person) {
   personService.save(person);
   return new ResponseEntity<String>("Ok", HttpStatus.OK);
 }

 @Repository
 public class PersonService {
   public void save(Person p) {
       // persistens code here
   }
 }

}

And here is the JUnit test. To keep the example as simple as possible, I have not included things such bean validation or any other advanced use of Mockito.


public class PersonControllerTest {

  @Mock
  private PersonController.PersonService personService;

  @InjectMocks
  private PersonController personController;

  private MockMvc mockMvc;

  @Before
  public void setup() {
     MockitoAnnotations.initMocks(this);
     mockMvc = MockMvcBuilders.standaloneSetup(personController).build();
  }

  @Test
  public void testAddPerson() throws Exception {

     String jsonAddPerson = "{" +
        "\"id\":1," +
        "\"name\":\"Lorem Ipsum\", " +
        "\"username\": \"lorem\", " +
        "\"email\": \"lorem@ipsum.com\"" +
     "}";

     mockMvc.perform(
     post("/admin/persons/add").contentType(MediaType.APPLICATION_JSON).content(jsonAddPerson))
     .andExpect(status().isOk());

     ArgumentCaptor<Person> personArgumentCaptor = ArgumentCaptor.forClass(Person.class);
     verify(personService, times(1)).save(personArgumentCaptor.capture());

     Person person = personArgumentCaptor.getValue();
     assertEquals("Lorem Ipsum", person.getName());
  }
}

The above example is very easy to extend so it should be straight forward. The important thing to notice in my example (as opposite to similar blogs) is how the “jsonAddPerson” string is used first in the JUnit test and then transformed into a fully populated Person object inside the Spring Controller. The second thing to notice is how I extract the transformed object out the Spring Controller to test ArgumentCaptor class from Mockito.

This entry was posted in Java, Spring. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>