使用JMockit模拟测试类的私有方法
我想模拟一个被测试类的私有方法但是方法在调用方法之后首先返回false两次,它应该返回false。 这是我试过的代码。 这是正在测试的类
public class ClassToTest { public void methodToTest() { Integer integerInstance = new Integer(0); boolean returnValue= methodToMock(integerInstance); if(returnValue) { System.out.println("methodToMock returned true"); } else { System.out.println("methodToMock returned true"); } System.out.println(); } private boolean methodToMock(int value) { return true; } }
考试class
import org.junit.Test; import static mockit.Deencapsulation.*; import mockit.*; public class TestAClass { @Tested ClassToTest classToTestInstance; @Test public void test1() { new NonStrictExpectations(classToTestInstance) { { invoke(classToTestInstance, "methodToMock", anyInt); returns(false); times = 2; invoke(classToTestInstance, "methodToMock", anyInt); returns(true); times = 1; } }; classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); } }
我这样做是为了得到理想的结果
final StringBuffer count = new StringBuffer("0"); new NonStrictExpectations(classToTestInstance) { { invoke(classToTestInstance, "methodToMock", anyInt); result= new Delegate() { boolean methodToMock(int value) { count.replace(0, count.length(), Integer.valueOf(Integer.valueOf(count.toString())+1).toString()); if(Integer.valueOf(count.toString())==3) { return true; } return false; } }; } };
使用期望(或严格期望)
使用Expectations和Deencapsulation.invoke()的组合,您可以部分模拟测试对象:
import org.junit.Test; import static mockit.Deencapsulation.*; import mockit.*; public class TestAClass { public static class ClassToTest { public void methodToTest() { boolean returnValue = methodToMock(0); System.out.println("methodToMock returned " + returnValue); } private boolean methodToMock(int value) { return true; } } @Tested ClassToTest classToTestInstance; @Test public void partiallyMockTestedClass() { new Expectations(classToTestInstance) {{ invoke(classToTestInstance, "methodToMock", anyInt); result = false; times = 2; }}; classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); } }
以上测试打印:
methodToMock returned false methodToMock returned false methodToMock returned true
当然,一般来说,我们应该避免嘲笑private
方法。 也就是说,我在实践中发现这样做有时很有用,通常当你有一个非常重要的私有方法并且已经通过另一个测试进行测试时; 在这种情况下,在第二次测试中模拟私有方法(对于不同的公共方法或通过相同的公共方法的不同路径)可能比设置必要的输入/条件容易得多。
使用NonStrictExpectations(在JMockit 1.23中已弃用)
使用NonStrictExpectations编写测试也很容易(OP的原始尝试不起作用,因为相同的非严格期望被记录两次 ,第二次记录覆盖了第一次):
@Test public void partiallyMockTestedClass() { new NonStrictExpectations(classToTestInstance) {{ invoke(classToTestInstance, "methodToMock", anyInt); returns(false, false, true); }}; classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); }
使用代表
如果需要更大的灵活性,我们总是可以记录基于Delegate
的结果:
@Test public void partiallyMockTestedClass() { new NonStrictExpectations(classToTestInstance) {{ invoke(classToTestInstance, "methodToMock", anyInt); result = new Delegate() { boolean delegate() { boolean nextValue = ...choose next return value somehow... return nextValue; } } }}; classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); classToTestInstance.methodToTest(); }
这对我有用: –
new MockUp() { @Mock boolean methodToMock(int value) { return true; } };
在这里,您可以使用模拟行为覆盖测试类的特定方法。
对于以下代码:
public class ClassToTest { public void methodToTest() { Integer integerInstance = new Integer(0); boolean returnValue= methodToMock(integerInstance); if(returnValue) { System.out.println("methodToMock returned true"); } else { System.out.println("methodToMock returned true"); } System.out.println(); } private boolean methodToMock(int value) { return true; } }
测试类将是:
public class ClassToTestTest{ @Test public void testMethodToTest(){ new Mockup(){ @Mock private boolean methodToMock(int value){ return true; } }; .... } }