跨类/方法模拟Java对象

时间:2018-06-04 21:57:10

标签: java mocking mockito powermockito

我正在使用Mockito / PowerMockito API来模拟junit案例的一些对象。 在下面给出的示例中,我想创建一个C类的模拟对象(由Utils.getC()返回)。另外我想在B.execute()中使用C的相同模拟对象,而不是新对象。有没有办法实现这个目标?请帮忙。 [更新 - 感谢Lino回答这个问题。我编辑了下面给出的代码。]

但是,这仅适用于静态方法。我无法模拟实例方法D.displayMessage()(从A.execute()和B.execute()调用)。

@PrepareForTest(mock.Utils.class)
@RunWith(PowerMockRunner.class)
public class TestMock {

    private static C c;
    private static D d;

    @BeforeClass
    public static void runOnceBeforeClass() {
        try {
            System.out.println("@BeforeClass - runOnceBeforeClass");
            PowerMockito.mockStatic(Utils.class);
            c = Mockito.mock(C.class);
            System.out.println("c = " + c);
            PowerMockito.doReturn("Hello!!").when(c).displayMessage();
            Answer<Void> answer = new Answer() {
                public Void answer(InvocationOnMock invocation) {
                    System.out.println("I can perform!");
                    return null;
                }
            };
            PowerMockito.doAnswer(answer).when(c).perform();
            PowerMockito.when(Utils.getC()).thenReturn(c);

            Answer<Void> answer1 = new Answer() {
                public Void answer(InvocationOnMock invocation) {
                    System.out.println("I can utilize!");
                    return null;
                }
            };
            PowerMockito.doAnswer(answer1).when(Utils.class);
            Utils.utilize();

            Answer<Void> answer2 = new Answer() {
                public String answer(InvocationOnMock invocation) {
                    System.out.println("I can run with params!");
                    return null;
                }
            };
            PowerMockito.doAnswer(answer2).when(Utils.class);
            Utils.runWithParams(Mockito.anyString(), Mockito.anyInt(), Mockito.any());
            d = PowerMockito.mock(D.class);
            PowerMockito.when(d.displayMessage()).thenReturn("D: I can display!");
            PowerMockito.whenNew(D.class).withNoArguments().thenReturn(d);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @AfterClass
    public static void runOnceAfterClass() {
        System.out.println("@AfterClass - runOnceAfterClass");
    }

    @Before
    public void runBeforeTestMethod() {
        System.out.println("@After - runBeforeTestMethod");
    }

    @After
    public void runAfterTestMethod() {
        System.out.println("@After - runAfterTestMethod");
    }

    @Test
    public void testExecution() {
        System.out.println(Utils.getC().displayMessage());
        A a = new A();
        a.execute();
    }
}

class A {
    public void execute() {
        System.out.println("executing A");
        B b = new B();
        b.execute();
        System.out.println(new D().displayMessage());
    }
}

class B {
    public void execute() {
        System.out.println("executing B");
        C c1 = Utils.getC();
        System.out.println("c = " + c1.hashCode());
        c1.perform();
        Utils.utilize();
        Utils.runWithParams("", 3, "2");
        System.out.println(new D().displayMessage());
    }
}

class C {
    public String displayMessage() {
        return "C: I can't display.";
    }
    public void perform() {
        System.out.println("I can't perform.");
    }
}

class D {
    public String displayMessage() {
        return "D: I can't display.";
    }
}

class Utils {
    public static C getC() {
        return null;
    }
    public static void utilize() {
        System.out.println("I can't unitilize.");
    }
    public static String runWithParams(String s, Integer i, Object o) {
        System.out.println("I can't run with params.");
        return "abc";
    }
}

1 个答案:

答案 0 :(得分:0)

如果您要重用C的模拟对象,则对于B的execute()方法内部的静态方法调用,可以重用相同的模拟对象。