DEV Community

loading...

Dependency Injection and Unit Testing with Mockito In Spring Boot Java

vtechjm profile image Kirk-Patrick Brown Updated on ・3 min read

So what is Dependency injection?

As the name suggest it is a software design technique for injecting dependencies.It is also one of the most important concepts in software development that allows engineers to develop highly testable and loosely coupled code.

Why is it important to unit testing and how does dependency injection help?

Unit tests are important for delivering high quality code and to ensure that the business logic executes as expected.As part of creating enterprise grade applications, eventually you will need to include some form of dependencies.These dependencies could be for example:

  • External Api resource
  • Underline Database used by your application

As part of the principles of test driven development(TDD), code under testing should avoid making calls to actual services and the use of test doubles which can take the form of mocks or stubs should be incorporated such as to avoid having flaky test.What are flaky test? These are automated test that can passed and fail without changes to your existing test cases, and are caused due to test relying on the actual dependencies vs utilising fake objects for the purpose of testing.Dependency injection then helps in testing by allowing these dependencies to be injected into the object that will use them, rather than having the dependencies tightly coupled to the object.

Ok,so how does it work in Spring Boot show me the code, Dependency injection and Inversion of Control (IoC)

The following list the structure of our project
Alt Text
We will create a Service for getting a user:

@Service
public class UserService{
    public User getUser() throws Exception {

        UnirestConfig.initialize();
        HttpResponse<User> user = Unirest.get("https://api.mocki.io/v1/ce5f60e2").asObject(User.class);
        return user.getBody();

    }
}

Enter fullscreen mode Exit fullscreen mode

Now that we have our service that is a project dependency.Lets create a RestController that will use this dependency.

package com.vtechjm.core.resources;

import com.vtechjm.core.services.UserService;
import com.vtechjm.core.services.models.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/Users")
class UserResource {
    private UserService userService;

    public UserResource(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/user")
    User getUser() throws Exception {
        return userService.getUser();

    }

}
Enter fullscreen mode Exit fullscreen mode

The key take away here is passing our dependency through the constructor.This is called constructor dependency injection.Notice there is no use of the new keyword here, and thus it is the client responsibility to create an instance and passed such dependency(IoC).Spring Boot will automatically manage the creation of the dependency here, by annotating with @Service a bean will be created.Below we will use Mockito to mock out what should be returned when the getUser method is called, simulating a fake service call.

Unit testing and mocking with Mockito


@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
    @Autowired
    private MockMvc mvc;
    @MockBean
    private UserService userServiceMock;
    @Test
    public void itShouldReturnAUser() throws Exception {
        //Arrange
        User mockUser = new User();
        mockUser.setCity("Santa Cruz");
        mockUser.setName("John Doe");
        Mockito.when(userServiceMock.getUser()).thenReturn(mockUser);
        //Act
        mvc.perform(get("/api/Users/user").contentType(MediaType.APPLICATION_JSON))
                .andExpect(
                        status().isOk()
                ).andExpect(
                jsonPath("$.name").value("John Doe")

        ).andExpect(
                jsonPath("$.city").value("Santa Cruz"));

    }
}

Enter fullscreen mode Exit fullscreen mode

Now that we have our working services as a dependency.In order to test this controller, we will use our AAA pattern of testing that, is:

  • Arrange
  • Act
  • Assert

We will set up our mock service in out test class for UserService, above spring boot will inject the dependency via the constructor from before.When we act on the method under testing here, our mock object will be returned and thus freeing us from the real service call being invoked each time our test runs.

Conclusion

As seen above Dependency injection is imperative to write loosely coupled and testable code.It adds to better code quality for the project overall.I hope this post was informative, the full source code can be found here.

Discussion (3)

pic
Editor guide

Some comments have been hidden by the post's author - find out more