Java单元测试--基于Mockito的PowerMock使用

Powermock 扩展于EasyMock和Mockito,而Mockito相对于EasyMock的优点其中一个是异常更清晰易懂。

 

现在用的是基于Mockito的Powermock,它可以mock静态方法,mock构造函数,mock void方法,mock部分方法,mock私有方法等。以下是如果使用基于Mockito的Powermock版本。

 

1.导入包

 其中 <powermock.version>1.6.3</powermock.version>

        <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-easymock</artifactId>
            <version>${powermock.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency> 
            <groupId>org.powermock</groupId> 
            <artifactId>powermock-api-mockito</artifactId> 
            <version>${powermock.version}</version> 
            <scope>test</scope> 
        </dependency>

 

假设我们需要测试下面的Hello类

 

class Hi {
    public void mockParentMethod() {
        System.out.println("mockSuperMethod Hi");
    }
}

class Hello extends Hi {
    private Kitty kitty;

    public Hello() {}
    
    public void mockParentMethod() {
        super.mockParentMethod();        
        System.out.println("mockParentMethod Hello");
    }
    public void mockNonStaticMethod() {
        String name = kitty.getName();
        System.out.println("mockNonStaticMethod" + name);
    }
    
    public void mockStaticMethod() {
        String name = Kitty.getName2();
        System.out.println("mockStaticMethod" + name);
    }
    
    public void partialMock() {
        _partialMock();
        System.out.println("partialMock");
    }

    private void _partialMock() {
        System.out.println("method3");
    }
    
    public void mockVoidMethod() {
        kitty.say3();
        System.out.println("partialMock");
    }

    public Kitty getKitty() {
        return kitty;
    }

    public void setKitty(Kitty kitty) {
        this.kitty = kitty;
    }
    
}

class Kitty {
    public String getName() {
        return "Kitty";
    }
    
    public static String getName2() {
        return "Kitty";
    }
    
    public void say3() {
        System.out.println("say3");
    }
}

 

 

2. 导入声明

测试类时,要导入以下声明:

 

@RunWith(PowerMockRunner.class)
public class HelloTest {
}

 

 

3. 测试方法

3.1 mock 非静态方法

 

    @Test
    public void testMockNonStaticMethod() {
        Hello hello = new Hello();
        Kitty kitty = PowerMockito.mock(Kitty.class);
        hello.setKitty(kitty);
        PowerMockito.when(kitty.getName()).thenReturn("test");
        hello.mockNonStaticMethod();
    }

 

 

3.2 mock 静态方法

首先需要PrepareForTest导入静态方法的类

 

@RunWith(PowerMockRunner.class)
@PrepareForTest({Kitty.class})
class HelloTest {
    @Test
    public void testMockStaticMethod() {
        Hello hello = new Hello();
        PowerMockito.mockStatic(Kitty.class);
        PowerMockito.when(Kitty.getName2()).thenReturn("test");
        hello.mockStaticMethod();
    }
}

 

 

3.3 partial mock (mock 部分方法)

如果只想mock一个类里面的个别方法,可以使用spy方法

 

@RunWith(PowerMockRunner.class)
@PrepareForTest({Hello.class})
public class HelloTest {
    @Test
    public void testPartialMock() {
        Hello hello = PowerMockito.spy(new Hello());
        try {
            PowerMockito.doReturn("test").when(hello, MemberMatcher.method(Hello.class, "_partialMock")).withNoArguments();
        } catch (Exception e) {
            e.printStackTrace();
        }
        hello.partialMock();
    }
}

 

 

3.4 mock void 方法

 

    @Test
    public void testMockVoidMethod() {
        Hello hello = new Hello();
        Kitty kitty = PowerMockito.mock(Kitty.class);
        hello.setKitty(kitty);
        PowerMockito.doNothing().when(kitty).say3();
        hello.mockVoidMethod();
    }

 

 3.5 mock parent method (父类方法)

使用PowerMockito.suppress()方法

    @Test
    public void testMockParentMethod() {
        Hello hello = new Hello();
        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(Hi.class));
        hello.testMockParentMethod();
    }

 不过这个版本好像有个bug,如果用了spy mock 子类,当子类方法里面调了父类的两次(或以上)相同或者不相同的方法时,测试子类的方法会报StackOverflowError异常,如下面的子类方法:

public void mockParentMethod() {
        super.mockParentMethod();       //一次 
        System.out.println("mockParentMethod Hello");
        super.mockParentMethod();       //两次
    }

@Test
    public void testMockParentMethod() {
        Hello hello = PowerMockito.spy(new Hello());
        PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(Hi.class));
        hello.testMockParentMethod();    // throw StackOverflowError exception
    }

 

3.6 测试私有方法

格式: PowerMockito.verifyPrivate(objectOrClassToInvoke).invoke("methodToBeTest", parms);

public void testPrivateMethod() {
	Hello hello = new  Hello();
	PowerMockito.verifyPrivate(hello).invoke("_partialMock");
}

或者使用 WhiteBox.invokeMethod() 方法。

 3.6 mock构造函数

使用 PowerMockito.whenNew() 方法

Hello hello = PowerMockito.mock(Hello.class)
PowerMockito.whenNew(Hello.class).thenReturn(hello);

 相关链接

powermock官网:https://github.com/jayway/powermock

 

猜你喜欢

转载自susiya.iteye.com/blog/2323366