SpringBoot unit testing tool --Mockito

Mockito is a Java mock frameworks, he was mainly used for mock tests, he can simulate any Spring-managed bean, the return value of simulation method to simulate throwing an exception ... and so on, until we know Mockito specific usage, must first understand what is a mock test

1. What is the mock test?

mock test is in the testing process, create a fake object, in order to test a method to avoid you, have to rely on their own to build the entire chain of bean

FIG less like this, need to call the class A and class B Class C, and Class B and Class C and needs to call other classes, such as D, E, F, etc., of Hypothesis D is an external service, it would be difficult to measure because your return will be directly affected by the results of the external service impact, cause your unit tests may be over today, but tomorrow it could not pass up

And when we introduce mock tests, you can create a fake object, replacing the real bean B and C, so call B, and C method, in fact, it would be to call the fake mock object methods, and we can set their own parameters and expected results of the mock object, so that we can focus on testing the current class a, and other external services will not be affected, so the test can improve the efficiency of many

2. Mockito Profile

Having the concept of mock tests, then we enter into today's topic, Mockito

Mockito is a Java mock frameworks, he mainly used for mock tests, he can simulate any Spring-managed bean, the return value of simulation method to simulate throwing an exception ... and so on, he will also call these analog recording method parameters, calling sequence, which can verify whether the object has been mock calls the correct order, and a call in accordance with desired parameters

Mockito can simulate such a service return data in unit tests, but not really to call the service, this is the spirit of mock tests mentioned above, that is, by simulating a fake service objects, to quickly test current I I want to test class

There Mockito, JMock, EasyMock .. in Java and other mainstream mock test tools, and built-in SpringBoot current framework is Mockito

Digression say something, Mockito is named from one mojito cocktails (Mojito), foreigners playing homophonic terrier. . .

3. In the test unit SpringBoot Mockito

First, the new spring-boot-starter-test relies at pom.xml, within which there is dependency contains JUnit, Mockito

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

First written a UserService, he there are two methods  getUserById() and  insertUser(), while they were going to go call UserDao the bean  getUserById() and  insertUser() methods

@Component
public class UserService {
    
    @Autowired
    private UserDao userDao;

    public User getUserById(Integer id) {
        return userDao.getUserById(id);
    }

    public Integer insertUser(User user) {
        return userDao.insertUser(user);
    }
}

User model is defined as follows

public class User {
    private Integer id;
    private String name;
    //省略 getter/setter
}

If this is not the first time we use Mockito simulate a fake userDao bean, but really to call a normal Spring bean of userDao then test class written as follows. Is actually very common injection userService bean, then to call his methods, and he would call again userDao obtain data from a database, and then we return to the results do assert assertion checks

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    //先普通的注入一个userService bean
    @Autowired
    private UserService userService;

    @Test
    public void getUserById() throws Exception {
        //普通的使用userService,他里面会再去调用userDao取得数据库的数据
        User user = userService.getUserById(1);
        
        //检查结果
        Assert.assertNotNull(user);
        Assert.assertEquals(user.getId(), new Integer(1));
        Assert.assertEquals(user.getName(), "John");
    }
}

But if userDao not write, want to first test userService, then you need to use to simulate a fake Mockito out userDao

Usage is a plus on userDao  @MockBean notes, when userDao been added to this annotation indicating Mockito will help us create a fake mock object, replacing the real userDao bean Spring already exists, that is, injection userService into the userDao bean, we have been replaced with a fake mock objects, so when we call the method userService again, will go to the call actually mock userDao bean's method, rather than a true userDao bean

When we create a fake userDao, we need userDao for the mock custom method return values, there is a formula usage, the meaning is the following code, when you call a method of a mock object, and returned customize pass the results we want

Mockito.when( 对象.方法名() ).thenReturn( 自定义结果 )

Use Mockito simulation bean unit tests the following specific examples

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
    
    @Autowired
    private UserService userService;
    
    @MockBean
    private UserDao userDao;

    @Test
    public void getUserById() throws Exception {
        // 定义当调用mock userDao的getUserById()方法,并且参数为3时,就返回id为200、name为I'm mock3的user对象
        Mockito.when(userDao.getUserById(3)).thenReturn(new User(200, "I'm mock 3"));
        
        // 返回的会是名字为I'm mock 3的user对象
        User user = userService.getUserById(1);

        Assert.assertNotNull(user);
        Assert.assertEquals(user.getId(), new Integer(200));
        Assert.assertEquals(user.getName(), "I'm mock 3");
    }
}

Mockito addition to the basic  Mockito.when( 对象.方法名() ).thenReturn( 自定义结果 ), also offers other usage allows us to use

thenReturn series method

When using any integer value when calling userService of getUserById () method, it returns a name for the object I'm user of mock3

Mockito.when(userService.getUserById(Mockito.anyInt())).thenReturn(new User(3, "I'm mock"));
User user1 = userService.getUserById(3); // 回传的user的名字为I'm mock
User user2 = userService.getUserById(200); // 回传的user的名字也为I'm mock

Only when the limit is three numerical parameters, will return I'm mock user name for the object 3

Mockito.when(userService.getUserById(3)).thenReturn(new User(3, "I'm mock"));
User user1 = userService.getUserById(3); // 回传的user的名字为I'm mock
User user2 = userService.getUserById(200); // 回传的user为null

When you call userService of insertUser () method, regardless of what passed in user that all return 100

Mockito.when(userService.insertUser(Mockito.any(User.class))).thenReturn(100);
Integer i = userService.insertUser(new User()); //会返回100

thenThrow series method

When the parameter when calling userService of getUserById () is 9:00, throws a RuntimeException

Mockito.when(userService.getUserById(9)).thenThrow(new RuntimeException("mock throw exception"));
User user = userService.getUserById(9); //会抛出一个RuntimeException

If the method does not return a value, then (that is defined as the method public void myMethod() {...}) to use doThrow () throws Exception

Mockito.doThrow(new RuntimeException("mock throw exception")).when(userService).print();
userService.print(); //会抛出一个RuntimeException

verify Series Methods

Check the call userService of getUserById (), and the parameters for the number 3 is 1 times

Mockito.verify(userService, Mockito.times(1)).getUserById(Mockito.eq(3)) ;

Calling sequence verification, verify userService first call getUserById () twice, and the first parameter is 3, the second parameter is 5, then call insertUser () method

InOrder inOrder = Mockito.inOrder(userService);
inOrder.verify(userService).getUserById(3);
inOrder.verify(userService).getUserById(5);
inOrder.verify(userService).insertUser(Mockito.any(User.class));

4. Mockito restriction

Mockito of the above is to use mock objects, but when Mockito in the mock objects, there are some restrictions need to comply

  • You can not mock static methods

  • You can not mock private methods

  • You can not mock final class

Therefore, when writing code, to do good functional split, to be able to use the mock Mockito technology to help us reduce the coupling of the bean test

5. Summary

Mockito is a very powerful framework that can help us in the implementation of unit test simulates a bean, to improve the stability of unit testing

And you can try to write code to write from the perspective of mock tests, and more able to write good code structure segmentation function, such as if there is the dedicated service and external communication code to extract into a bean, making unit when testing, as long as the replacement of the bean through Mockito out on the line

Published 656 original articles · won praise 331 · views 310 000 +

Guess you like

Origin blog.csdn.net/Dome_/article/details/104226674
Recommended