Spring Boot with TDD — Part II

Sheik Arbaz
3 min readMay 8, 2019

--

Hello people!

Make sure that you complete Part I, before coming here.

At the end of the last blog post we’ve added some data in our H2 Database using the interface CommandLineRunner. In this blog we are going to add an API to save a todo. So, remove that bean code from ToDoApplication.java. Make sure it looks like below.

@SpringBootApplication
public class TodoApplication {

public static void main(String[] args) {
SpringApplication.run(TodoApplication.class, args);
}

}

Let’s start coding…!

Controller

Let’s write the test in ToDoControllerTest.java. Whenever we send an object to the controller, we expect it to return the same object. So, we’ll send an object in the post request and verify the returned object. Let’s follow the AAA pattern.

Arrange

It’s the setup time. Mock the dependency i.e., service.

@Test
void successfullyCreateAToDo(){
ToDo eatToDo = new ToDo(1L, "Eat thrice", true);
when(toDoService.save(any(ToDo.class))).thenReturn(eatToDo);
}

Create a dummy save method in the service.

public ToDo save(ToDo toDo) {
return new ToDo();
}

We have to make a JSON and hit our api with it. We’ll use objectMapper utility to convert our Java Object to JSON.

ObjectMapper objectMapper = new ObjectMapper();
String eatToDoJSON = objectMapper.writeValueAsString(eatToDo);

Act

As usual, we’ll use a MockMvc object to perform our action.

ResultActions result = mockMvc.perform(post("/todos")
.contentType(MediaType.APPLICATION_JSON)
.content(eatToDoJSON)
);

Assert

Time to assert things. We expect a 201 http status on successful resource creation.

result.andExpect(status().isCreated())
.andExpect(jsonPath("$.text").value("Eat thrice"))
.andExpect(jsonPath("$.completed").value(true));

Congratulations! Now, we’ve a failing test case. It’s failing as the end point we’re trying to hit, doesn’t exist. Let’s fix the test case by adding the end point in ToDoController.java.

@PostMapping("/todos")
ResponseEntity<ToDo> create(@RequestBody ToDo toDo) {
return new ResponseEntity<>(toDoService.save(toDo), HttpStatus.CREATED);
}

Hurrah! The test is passing now.

Service

Let’s follow the AAA pattern. We’ll assert the number of elements in the repository.

@Test
void saveAToDo() {
ToDoService toDoService = new ToDoService(toDoRepository);
ToDo todoSample = new ToDo("Todo Sample 1",true);

toDoService.save(todoSample);

assertEquals(1.0, toDoRepository.count());
}

It’s failing as we’ve not implemented save in the service. Let’s do it now.

public ToDo save(ToDo toDo) {
return toDoRepository.save(toDo);
}

Now. It’s passing.

Run all the test cases in the service, one of them is failing… Why? Why? Why….?

If we observe, We’ve a repository in the service which is getting modified in each test case but we’re asserting their results independently. No, No, it’s not fair. We want each test case to run independently. For that purpose, we’ll clear the repository after running each test case. We’ve an annotation called AfterEach provided by JUnit 5, the method marked with it will run after each test case/method.

@AfterEach
void tearDown(){
toDoRepository.deleteAll();
}

Run… Hey!!! Now all are passing.

Run the Application

Now, run the application……. save few todos!

Do a POST Request → http://localhost:8080/todos/

Content-Type: application/json

json: {“text” : “ToDo Sample”, “completed” : “false” }

POST Request

And it returns the same ToDo with 201 http status.

Response Entity

Like this, add few more.

Now, hit the endpoint to get all the todo’s.

Do a GET Request → http://localhost:8080/todos/

Hurrah! It’s all working fine.

Part III will be published soon. Git Repository.

--

--