Using PowerMockito to achieve single test

The purpose of the PowerMock

PowerMock is mainly used to Mock classes and methods in a single test. Tools that isolate external dependencies and focus on the logic of your code. The advantage over Mockito is that you can mock static classes, private methods

Maven rely on

The existing code uses the following dependencies, which will be increased or decreased according to the actual situation.

<! --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <! Mockito </groupId> <artifactId>mockito </artifactId> <version>${mockito.version}</version> <scope>test</scope> </dependency> <! --> <dependency> <groupId>org.powermock</groupId> <artifactId> Powermock-module-junit4 </artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency> <! --> <dependency> <groupId>org.powermock</groupId> <artifactId>powermock API -mockito2</artifactId> <version>${powermock.version}</version> <scope>test</scope> </dependency>Copy the code

use

The mock static class

  1. Specify RunWith as PowerMockRunner. Class;
  2. PrePareForTest specifies the class of the static class to test. For example, I specified CommonUtil.class;
  3. MockStatic class that mocks before using powerMockito.mockStatic;
  4. Powermockito.when (method).thenreturn (result);

Note Indicates a problem to be verified

Scenario: Methods in the project need to use many static methods, for ease of development; I mock the test method in the first step. I mock the test method in the first step. I mock the test method in the second step, and the result of the first mock is null.

Imagine: On step 3 the second time, a static class is mock again and the previous stub information is cleared, resulting in null

import com.autonavi.dc.cms.common.mapobj.MapObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import tool.common.util.CommonUtil;

@RunWith(PowerMockRunner.class)
@PrepareForTest({CommonUtil.class})
public class StaticMockDemo {

    @Before
    public void init(a) {
        PowerMockito.mockStatic(CommonUtil.class);
    }

    @Test
    public void testStr2Map(a) {
        PowerMockito.when(CommonUtil.str2MapObj(Mockito.any())).thenReturn(newMapObject()); }}Copy the code

Mock private methods

Mock some private methods as well. 1. Mock the class using the powerMockito.spy () method. 2. Use when(spy,” method name “, parameter…) Method to execute the private method

   @Test
    public void testMockPrivateMethod(a) {
        MockDemo spy = PowerMockito.spy(new MockDemo());
        PowerMockito.doReturn(new ArrayList<>()).when(spy, "privateMethod", Mockito.any());
    }
Copy the code

Assign a value to a private member variable

@Test
    public void test(a) {
        MockDemo spy = PowerMockito.spy(new MockDemo());
        // Assign values to private member variables
        MemberModifier.field(MockDemo.class, "privateFieldX").set(spy, "privateFieldXValue");
    }
Copy the code

Gets the value of a private member variable

@Test
    public void test(a) {
        MockDemo spy = PowerMockito.spy(new MockDemo());
        MemberModifier.field(MockDemo.class, "privateFieldX").set(spy, "privateFieldXValue");
        // Get the value of a private variable
        String fileValue = (String) MemberModifier.field(MockDemo.class, "privateFieldX").get(spy);
    }
Copy the code

Some problems in the use of PowerMockito

DoReturn (). When () and when () thenReturn ()

Scene:

When writing a single test using PowerMockito, THERE was a method I needed to mock out and I couldn’t get into the actual method. So use when.. ThenReturn the result into the method that needs to mock, error!

When… doReturn… Returns the actual method before returning the result, but only returns the data when the result is returned. If you don’t want to enter a method, you can use doreturn… When, which skips the method and returns the result directly.

Resources Stack Overflow: stackoverflow.com/questions/2…

The following use case is also taken from Stack Overflow

Example:

// example
public class MyClass {
     protected String methodToBeTested(a) {
           return anotherMethodInClass();
     }

     protected String anotherMethodInClass(a) {
          throw newNullPointerException(); }}Copy the code

The Test:

@Spy
private MyClass myClass;

// ...

// would work fine
doReturn("test").when(myClass).anotherMethodInClass();

// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");
Copy the code

** Note: **doReturn().when() is used, if the method in when is private, it is still executed, not skipped

Other usage methods to be updated…