Java 使用 JMockit 模拟被测类的私有方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24427685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mocking private method of class under test using JMockit
提问by Varun
I want to mock private method of a class under test but method return false first two times when the method is called after that it should return false. Here is the code what I tried. This is the class which is being tested
我想模拟一个被测类的私有方法,但是当该方法被调用时,方法前两次返回 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;
}
}
Test 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();
}
}
I did this to get desired results
我这样做是为了得到想要的结果
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;
}
};
}
};
采纳答案by Rogério
Using Expectations (or StrictExpectations)
使用期望(或 StrictExpectations)
Using a combination of Expectations and Deencapsulation.invoke(), you can partially mock the tested object:
使用 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();
}
}
The test above prints:
上面的测试打印:
methodToMock returned false
methodToMock returned false
methodToMock returned true
In general, of course, we should avoid mocking private
methods. That said, I have found in practice that it issometimes useful to do so, typically when you have a private method which does something non-trivial and was already tested by another test; in such a case, mocking that private method in a second test (either for a different public method or a different path through the same public method) may be significantly easier than setting up necessary inputs/conditions.
一般来说,当然,我们应该避免嘲笑private
方法。这就是说,我在实践中发现,它是有时是有用的话,通常当你有哪些做了不平凡的,并已经由另一个测试测试的私有方法; 在这种情况下,在第二个测试中模拟该私有方法(对于不同的公共方法或通过相同公共方法的不同路径)可能比设置必要的输入/条件容易得多。
Using NonStrictExpectations (deprecated in JMockit 1.23)
使用 NonStrictExpectations(在 JMockit 1.23 中已弃用)
It's just as easy to write the test with a NonStrictExpectations (the original attempt by the OP didn't work only because the same non-strict expectation was recorded twice, with the second recording overriding the first):
使用 NonStrictExpectations 编写测试也同样容易(OP 的最初尝试并没有奏效,因为相同的非严格期望被记录了两次,第二次记录覆盖了第一次):
@Test
public void partiallyMockTestedClass() {
new NonStrictExpectations(classToTestInstance) {{
invoke(classToTestInstance, "methodToMock", anyInt);
returns(false, false, true);
}};
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
classToTestInstance.methodToTest();
}
Use a Delegate
使用委托
If more flexibility is needed, we can always record a Delegate
-based result:
如果需要更多的灵活性,我们总是可以记录一个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();
}
回答by Kaushik
This works for me:-
这对我有用:-
new MockUp<ClassToTest>() {
@Mock
boolean methodToMock(int value) {
return true;
}
};
回答by Amit Kaneria
Here, you can over-ride a particular method of the testing class with mock behavior.
在这里,您可以使用模拟行为覆盖测试类的特定方法。
For the below code:
对于以下代码:
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;
}
}
Test class would be:
测试类将是:
public class ClassToTestTest{
@Test
public void testMethodToTest(){
new Mockup<ClassToTest>(){
@Mock
private boolean methodToMock(int value){
return true;
}
};
....
}
}