我有一个名为Java的Java类MyClass,我想用JUnit进行测试。methodA我要测试的公共方法调用methodB同一类中的私有方法,以确定要遵循的条件路径。我的目标是为中的不同路径编写JUnit测试methodA。另外,methodB调用服务,因此我不希望在运行JUnit测试时实际执行该服务。
MyClass
methodA
methodB
模拟methodB和控制其返回值以便我可以测试“ methodA”的不同路径的最佳方法是什么?
我更喜欢在编写模拟时使用JMockit,因此我对适用于JMockit的任何答案特别感兴趣。
这是我的示例类:
public class MyClass { public String methodA(CustomObject object1, CustomObject object2) { if(methodB(object1, object2)) { // Do something. return "Result"; } // Do something different. return "Different Result"; } private boolean methodB(CustomObject custObject1, CustomObject custObject2) { /* For the sake of this example, assume the CustomObject.getSomething() * method makes a service call and therefore is placed in this separate * method so that later an integration test can be written. */ Something thing1 = cobject1.getSomething(); Something thing2 = cobject2.getSomething(); if(thing1 == thing2) { return true; } return false; } }
这是我到目前为止所拥有的:
public class MyClassTest { MyClass myClass = new MyClass(); @Test public void test_MyClass_methodA_enters_if_condition() { CustomObject object1 = new CustomObject("input1"); CustomObject object2 = new CustomObject("input2"); // How do I mock out methodB here to return true? assertEquals(myClass.methodA(object1, object2), "Result"); } @Test public void test_MyClass_methodA_skips_if_condition() { CustomObject object1 = new CustomObject("input1"); CustomObject object2 = new CustomObject("input2"); // How do I mock out methodB here to return false? assertEquals(myClass.methodA(object1, object2), "Different Result"); } }
谢谢!
给出您要求的答案(使用JMockit的部分模拟):
public class MyClassTest { @Tested MyClass myClass; @Test public void test_MyClass_methodA_enters_if_condition() { final CustomObject object1 = new CustomObject("input1"); final CustomObject object2 = new CustomObject("input2"); new NonStrictExpectations(myClass) {{ invoke(myClass, "methodB", object1, object2); result = true; }}; assertEquals("Result", myClass.methodA(object1, object2)); } @Test public void test_MyClass_methodA_skips_if_condition() { final CustomObject object1 = new CustomObject("input1"); final CustomObject object2 = new CustomObject("input2"); new NonStrictExpectations(myClass) {{ invoke(myClass, "methodB", object1, object2); result = false; }}; assertEquals("Different Result", myClass.methodA(object1, object2)); } }
但是,我 不 建议这样做。通常,private不应模拟方法。而是模拟被测单元的实际外部依赖关系(CustomObject在这种情况下):
private
CustomObject
public class MyTestClass { @Tested MyClass myClass; @Mocked CustomObject object1; @Mocked CustomObject object2; @Test public void test_MyClass_methodA_enters_if_condition() { new NonStrictExpectations() {{ Something thing = new Something(); object1.getSomething(); result = thing; object2.getSomething(); result = thing; }}; assertEquals("Result", myClass.methodA(object1, object2)); } @Test public void test_MyClass_methodA_skips_if_condition() { new NonStrictExpectations() {{ object1.getSomething(); result = new Something(); object2.getSomething(); result = new Something(); }}; assertEquals("Different Result", myClass.methodA(object1, object2)); } }