使用PowerMock的EasyMock私有方法模拟

时间:2020-02-23 14:41:18  来源:igfitidea点击:

有时我们想测试使用私有方法的方法。
我们可以使用EasyMock创建模拟对象,但EasyMock不允许我们模拟私有方法。
因此,我们可以使用PowerMock EasyMock API扩展来模拟类私有方法。

使用PowerMock的EasyMock私有方法模拟

为了消除私有方法的行为,我们必须使用PowerMock.createPartialMock()来获取模拟对象。
这是必需的,这样我们才不会在调用这些私有方法的地方嘲笑这些方法。

在那之后,使用PowerMock.expectPrivate()方法来存根私有方法的行为。

在编写使用存根方法的测试代码之前,请确保调用PowerMock.replay()
对于存根方法调用验证,请使用PowerMock.verify()方法。

EasyMock私有方法– JUnit 4

PowerMock目前不支持JUnit 5,因此我将使用JUnit 4编写测试用例。

假设我们有一个定义为的类:

class Foo {
	private boolean isInit() {
		return false;
	}
	private String reverse(String s) {
		return null;
	}
	public boolean checkStatus() {
		return isInit();
	}
	public String doReverse(String s) {
		return reverse(s);
	}
}

注意,公共方法在内部调用类的私有方法。

这是我们其中测试私有方法行为的测试类。

package com.theitroad.easymock.powermock.privatemethod;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.powermock.api.easymock.PowerMock.*;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Foo.class)
public class JUnit4PowerMockEasyMockPrivateExample {

	@Test
	public void test_private_method() throws Exception {
		Foo mock = createPartialMock(Foo.class, "isInit", "reverse");
		
		expectPrivate(mock, "isInit").andReturn(true);
		expectPrivate(mock, "reverse", "cat").andReturn("tac");
		expectPrivate(mock, "reverse", "123").andReturn("321");
		replay(mock);
		
		assertTrue(mock.checkStatus());
		assertEquals("tac", mock.doReverse("cat"));
		assertEquals("321", mock.doReverse("123"));
		
		verify(mock);
	}
}

请注意,我们仅为私有方法创建部分模拟,未模拟公共方法。
因此,当我们调用这些公共方法时,将调用真正的方法,该方法将在内部调用私有方法,并且将使用我们的存根方法实现。

EasyMock专用方法– TestNG

这是用TestNG测试框架编写的模拟私有方法的示例。

package com.theitroad.easymock.powermock.privatemethod;

import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.testng.PowerMockTestCase;
import org.testng.annotations.Test;

import static org.powermock.api.easymock.PowerMock.*;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;

@PrepareForTest(Foo.class)
public class TestNGPowerMockEasyMockPrivateExample extends PowerMockTestCase{

	@Test
	public void test_private_method() throws Exception {
		Foo mock = createPartialMock(Foo.class, "isInit", "reverse");
		
		expectPrivate(mock, "isInit").andReturn(true);
		expectPrivate(mock, "reverse", "cat").andReturn("tac");
		expectPrivate(mock, "reverse", "123").andReturn("321");
		replay(mock);
		
		assertTrue(mock.checkStatus());
		assertEquals("tac", mock.doReverse("cat"));
		assertEquals("321", mock.doReverse("123"));
		
		verify(mock);
	}
}

注意,TestNG类扩展了PowerMockTestCase类,因此PowerMock API用于运行测试用例。