The new Certification Class of Learn Spring Security is out:

>> CHECK OUT THE COURSE

1. Overview

This article will show how to use dependency injection to insert Mockito mocks into Spring Beans for unit testing.

In real-world applications, where components often depend on accessing external systems, it is important to provide proper test isolation so that we can focus on testing the functionality of a given unit without having to involve the whole class hierarchy for each test.

Injecting a mock is a clean way to introduce such isolation.

2. Maven Dependencies

The following Maven dependencies are required for the unit tests and the mock objects:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>1.3.1.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>1.3.1.RELEASE</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.8.9</version>
</dependency>

We decided to use Spring Boot for this example, but classic Spring will also work fine.

3. Writing the Test

3.1. The Business Logic

First, we are going to write the business logic that will be tested:

@Service
public class NameService {
    public String getUserName(String id) {
        return "Real user name";
    }
}

The NameService class will be injected into:

@Service
public class UserService {

    private NameService nameService;

    @Autowired
    public UserService(NameService nameService) {
        this.nameService = nameService;
    }

    public String getUserName(String id) {
        return nameService.getUserName(id);
    }
}

For this tutorial, the given classes return a single name regardless of the id provided. This is done so that we don’t get distracted by testing any complex logic.

We will also need a standard Spring Boot main class to scan the beans and initialize the application:

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

3.2. The Tests

Now let’s move on to the test logic. First of all, we have to configure application context for the tests:

@Profile("test")
@Configuration
public class NameServiceTestConfiguration {
    @Bean
    @Primary
    public NameService nameService() {
        return Mockito.mock(NameService.class);
    }
}

The @Profile annotation tells Spring to apply this configuration only when the “test” profile is active. The @Primary annotation is there to make sure this instance is used instead of a real one for autowiring.  The method itself creates and returns a Mockito mock of our NameService class.

Now we can write the unit test:

@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MocksApplication.class)
public class UserServiceTest {

    @Autowired
    private UserService userService;

    @Autowired
    private NameService nameService;

    @Test
    public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() {
        Mockito.when(nameService.getUserName("SomeId")).thenReturn("Mock user name");
        String testName = userService.getUserName("SomeId");
        Assert.assertEquals("Mock user name", testName);
    }
}

We use the @ActiveProfiles annotation to enable the “test” profile and activate the mock configuration we wrote earlier. Because of this, Spring autowires a real instance of the UserService class, but a mock of the NameService class. The test itself is a fairly typical JUnit+Mockito test. We configure the desired behavior of the mock, then call the method which we want to test and assert that it returns the value that we expect.

It is also possible (though not recommended) to avoid using environment profiles in such tests. To do so, remove the @Profile and @ActiveProfiles annotations and add an @ContextConfiguration(classes = NameServiceTestConfiguration.class) annotation to the UserServiceTest class.

4. Conclusion

The tutorial showed how to inject Mockito mocks into Spring Beans. The implementation can be found in the example GitHub project.

Go deeper into Spring Security with the course:

>> LEARN SPRING SECURITY

Sort by:   newest | oldest | most voted
Marcin
Guest

One small remark. It would be better to use mockito-core instead of mockito-all
as a dependency. More details: https://solidsoft.wordpress.com/2012/09/11/beyond-the-mockito-refcard-part-3-mockito-core-vs-mockito-all-in-mavengradle-based-projects/ . What is more with the newest beta versions of Mockito 2 it would not be even possible as -all artifact is no longer produced.

Eugen Paraschiv
Guest

Hey Marcin,
First – thanks for the feedback, that’s a good point. I updated the article to only use core, since that’s really all we need here.
Also, I’m a reader of your blog, keep up the good work. Cheers,
Eugen.

Sujit Tripathy
Guest

Hey Eugen
Can we write the Mockito test class to test a module in spring without the spring application context? I mean without @RunWith(SpringJUnit4ClassRunner.class). I have a service class and a repository (autowired) where I want to test just the service class with Mockito with junit. Thanks in advance.
Thanks
Sujit

Grzegorz Piwowarek
Guest

Yes, sure. Spring is not obligatory for using Mockito 🙂 Just remember about using appropriate JUnit Mockito Runner instead of SpringJUnit4ClassRunner

Sujit Tripathy
Guest

Thank you for the response. Is there any best practice to use what type of unit testing framework along with Spring from both TDD & BDD perspective. I came across various topics on this like Mockito, Junit (which is ofcouse the primary), Spring mock, assertJ (which Pivotal uses) so trying to think which combination is best to follow and give much better output.

Grzegorz Piwowarek
Guest

Well, for me JUnit + Mockito + AssertJ(I am actually one of the commiters so I might be biased) works great. There are other mocking frameworks but mockito is the keeper in most cases. Another set of tools worth checking outwould be Groovy + Spock

Sujit Tripathy
Guest

Appreciate your quick response. Thank you so much on these perspectives.

wpDiscuz