Java Unit Test Powermockito and Mockito Use Summary

  • 2021-11-10 09:28:26
  • OfStack

Directory dependency introduction
Use of PowerMockito
Use mockito for mock instances
Static invocation of Redis by mock
mock singleton class
mock Private Method
PowerMock Skip Method Execution
Summarize
Reference document

Recently, the company is promoting the unit test of Java application, which requires that the coverage rate of unit test be increased to over 50% to ensure that the online code is fully self-tested. Company unit testing framework selected Junit 4.12, Mock framework selected Mockito and PowerMock, and selected JaCoCo to do coverage testing, the following details of my use of these frameworks 1 experience.

Dependency introduction


<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.8.9</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.7.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>1.7.4</version>
    <scope>test</scope>
</dependency>

Use of PowerMockito

The popular Mock frameworks such as Mockito, EasyMock and JMock have a common disadvantage. Neither mock static, final, private method, etc., PowerMock can perfectly solve the shortcomings of the above framework. Next, let's take a look at how the omnipotent PowerMock solves the above problems. Let's look at an example first. The following code is a class that needs to be tested. The tested class not only calls Spring Bean, but also includes static reading of Redis, and also uses getInstance () singleton class. Now, let's come to the above external class of mock on 11.

Single test class (mainly test queryStudentScoreByKeyword method)


@Component
public class StudentService {

    @Resource
    private StudentDao studentDao;

    public List<StudentBo> queryStudentScoreByKeyword(String name) {
        System.out.println("invoke StudentService.queryStudentScoreByKeyword ...");

        List<StudentBo> cacheList = RedisUtils.getArray(name, StudentBo.class);
        if (CollectionUtils.isNotEmpty(cacheList)) {
            return cacheList;
        }
        String keyword = processKeyword(name);
        List<Student> students = studentDao.queryStudentByKeyWord(keyword);
        List<Integer> ids = students.stream().map(Student::getId).collect(Collectors.toList());
        List<Person> personList = SchoolManageProxy.getInstance().queryPerson(ids);

        List<StudentBo> studentBos = CommonUtils.toBo(personList, students);
        //  Highlight the result 
        highlightResult(studentBos, name);
        //  Cache to Redis
        RedisUtils.setArray(name, studentBos, 10 * 60);
        return studentBos;
    }

    private String processKeyword(String name) {
        System.out.println("invoke StudentService.processKeyword ...");
        String newName = name;
        // do somethings
        return newName;
    }

    private void highlightResult(List<StudentBo> result, String name) {
        System.out.println("invoke StudentService.highlightResult ...");
        // do keyword highlight
    }

}

Single test class


@RunWith(PowerMockRunner.class)
@PrepareForTest({SchoolManageProxy.class, RedisUtils.class, StudentService.class})
// @PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})
@SuppressStaticInitializationFor({"cn.ganzhiqiang.ares.unittest.SchoolManageProxy"})
public class StudentServiceTest {

    @Mock
    private StudentDao mockStudentDao;

    @InjectMocks
    private StudentService studentServiceUnderTest;

    @Before
    public void setUp() {
        initMocks(this);
    }

    @Test
    public void testQueryStudentScoreByKeyword() throws Exception {
        studentServiceUnderTest = PowerMockito.spy(studentServiceUnderTest);
        PowerMockito.mockStatic(RedisUtils.class);
        PowerMockito.mockStatic(SchoolManageProxy.class);

        // mock Singleton call 
        SchoolManageProxy mockSchoolManageProxy = PowerMockito.mock(SchoolManageProxy.class);
        PowerMockito.when(SchoolManageProxy.getInstance()).thenReturn(mockSchoolManageProxy);
        when(mockSchoolManageProxy.queryPerson(anyList())).thenReturn(Collections.emptyList());

        // mock Drop right Redis Static invocation of 
        PowerMockito.when(RedisUtils.getArray(eq("tom"), eq(StudentBo.class))).thenReturn(Collections.emptyList());
        //  Displayed mock Drop the static void The method of (you can not mock ) 
        PowerMockito.doNothing().when(RedisUtils.class, "setArray", anyString(), anyList(), anyInt());

        // mock Private method processKeyword
        PowerMockito.doReturn("tom").when(studentServiceUnderTest, "processKeyword", anyString());

        //  Skip private methods highlightResult Execution of 
        PowerMockito.suppress(PowerMockito.method(StudentService.class, "highlightResult"));

        //  Use Mockito Come mock Invoke of service 
        when(mockStudentDao.queryStudentByKeyWord(anyString())).thenReturn(Collections.emptyList());

        // Run the test
        final List<StudentBo> result = studentServiceUnderTest.queryStudentScoreByKeyword("tom");

    }
}

Use mockito for mock instances

First, we use Mockito to call Spring Bean. Mockito. mock can be used for mock1 instances. We use @ Mock annotation here, and the effect is one.


//  Use Mockito Come mock Invoke of service  
when(mockStudentDao.queryStudentByKeyWord(anyString())).thenReturn(Collections.emptyList());

Static invocation of Redis by mock

Next, we use PowerMock to use mock to call static methods. Note that we need to add RedisUtils class to @ PrepareForTest annotation. We have mock getArray method and mock setArray method. In fact, setArray does not need mock explicit mock here


PowerMockito.mockStatic(RedisUtils.class);
// mock Drop right Redis Static invocation of 
PowerMockito.when(RedisUtils.getArray(eq("tom"), eq(StudentBo.class))).thenReturn(Collections.emptyList());
//  Explicit mock Drop the static void The method of (you can not mock ) 
PowerMockito.doNothing().when(RedisUtils.class, "setArray", anyString(), anyList(), anyInt());

mock singleton class

mock singleton class is relatively complex 1 point, logically, first use Powermock mock singleton class, and then give the singleton class getInstance method piling, return to the previous mock, and then pile the method actually called by mock class. The code is as follows


PowerMockito.mockStatic(SchoolManageProxy.class);
// Powermock mock Singleton class 
SchoolManageProxy mockSchoolManageProxy = PowerMockito.mock(SchoolManageProxy.class);
//  For singleton classes getInstance Method piling 

PowerMockito.when(SchoolManageProxy.getInstance()).thenReturn(mockSchoolManageProxy);
//  Right mock Class queryPerson Method of piling 
when(mockSchoolManageProxy.queryPerson(anyList())).thenReturn(Collections.emptyList());

mock Private Method

It can be seen that the queryStudentScoreByKeyword method calls the private method processKeyword of this class. If this method takes too long, powermock can also be used for mock. It should be noted that studentServiceUnderTest needs spy () for mock


// mock  Instances 
// spy The standard is: If you don't pile, the real method is executed by default, and if you pile, you return to the pile implementation. 
studentServiceUnderTest = PowerMockito.spy(studentServiceUnderTest);
// mock Private method processKeyword
// doReturn(...) when(...) Do not make real calls, but when(...) thenReturn(...) The original method is actually called, but the specified result is returned 
PowerMockito.doReturn("tom").when(studentServiceUnderTest, "processKeyword", anyString());

PowerMock Skip Method Execution

You can also skip the execution of private methods with PowerMock


//  Skip private methods highlightResult Execution of 
PowerMockito.suppress(PowerMockito.method(StudentService.class, "highlightResult"));

Summarize

I seldom write single test when writing code before. Since the company forced to improve the coverage rate of single test, although the development efficiency slowed down, it really caused me to pay attention to single test, and then studied Mock frameworks such as PowerMockito and Mokcito. Powermock is all-powerful because it uses custom loaders and bytecode manipulation techniques. At the same time, it is 10 points easy to use, and it is really an excellent framework.

Demo Address: https://github.com/LJWLgl/mock-data

Reference document

PowerMock
In-depth practice of powermockito unit testing
Talking about PowerMock of test
Omnipotent PowerMock, mock private method, static method, test private method, final class
Differences between Mock and Spy


Related articles: