Zach Cochran
by Zach Cochran
2 min read

Categories

Tags

The great thing about tutorials is that the usually only show you just enough to get your feet wet, and then set you on your own to fall on your face. This seems to be especially true when it comes to writing unit tests for your code. Tonight I spent about an hour just trying to get two simple unit test cases working for the stupid mongoDB sample app I posted about yesterday.

I eventually came across two resources that kind of sorta helped me out.

The first was this tutorial example which provided a generic overview of how to test spring REST apis using the various spring mocking tools. But it didn’t get me to where I needed to be when mocking mongoDB data.

For that, I found an actual code example from someones project. Being able to see how they structured their tests for their controller piece really helped me out.

And so that’s what I focused on tonight, writing some basic GET tests for my controller (as that’s really the only piece I have to test).

When it comes to testing, the goal is to keep your focus on what the file is doing. If it’s a controller, focus on the routing and responses. If it’s the business logic, focus on how the function/method is handling your I/O.

So tonight the main thing I needed to figure out was how to get this stupid data mocked up so that it could be used and returned in the requests. Here is what I ended up with at the end of the night:

package com.example.mongodb.springboot_mongodb;

import com.example.mongodb.springboot_mongodb.models.Pets;
import com.example.mongodb.springboot_mongodb.repositories.PetsRepository;
import org.bson.types.ObjectId;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import java.util.Collections;

import static org.junit.Assert.*;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@WebMvcTest(value = PetsController.class, secure = false)
public class PetsControllerTest {

   @Autowired
   private MockMvc mockMvc;

   @MockBean
   private PetsRepository petsRepository;

   private ObjectId newId = ObjectId.get();
   Pets mockPets = new Pets(this.newId, "Bob", "dog", "poodle");

   @Test
   public void getAllPets() throws Exception {
       given(this.petsRepository.findAll()).willReturn(Collections.singletonList(mockPets));
       this.mockMvc.perform(get("/pets/").accept(MediaType.APPLICATION_JSON))
               .andExpect(status().isOk())
               .andExpect(content().string("[{\"_id\":\""+this.newId.toHexString()+"\",\"name\":\"Bob\",\"species\":\"dog\",\"breed\":\"poodle\"}]"));
   }

   @Test
   public void getPetById() throws Exception {
       given(this.petsRepository.findBy_id(this.newId)).willReturn(mockPets);
       this.mockMvc.perform(get("/pets/"+this.newId.toHexString()).accept(MediaType.APPLICATION_JSON))
               .andExpect(status().isOk())
               .andExpect(content().string("{\"_id\":\""+this.newId.toHexString()+"\",\"name\":\"Bob\",\"species\":\"dog\",\"breed\":\"poodle\"}"));
   }
}

From what I understand so far, we set up the test telling it to use the MockMvc to help us to test our controller. We associate it with the correct controller class so it knows where the requests are heading to. When we simulate the requests, it’s done using this MockMvc that we create.

In order to tell the test case to use our mocked version of the database (not using the real one for testing), we use the given statement to set up the condition which will cause our mock data to be used. When we send the request which will satisfy that condition, the mock data is accessed instead of the DB.

And that’s where I’m at so far. There’s a whole lot more I need to understand better, and another 3 methods I need to write tests for. I’m not even sure everything I explained above is correct, but it’s where my understanding is at now after this first evening with it.

💚