如何模拟父类中受保护的方法?

4

我试图模拟父类中受保护的方法。为此,我使用了MockitoPowerMockito。以下是我的父类。

public class Parent {
    protected int foo() {
        throw new RuntimeException("Do not invoke this method.");
    }
}

我的子类。

public class Child extends Parent {
    protected int boo() {
        return super.foo();
    }
}

测试类。

@RunWith(PowerMockRunner.class)
@PrepareForTest({Parent.class, Child.class})
public class ChildTest {

    @Mock
    private Child childMock;

    @Before
    public void before() {
        initMocks(childMock);
    }

    @Test
    public void shouldInvokeProtectedMockedMethod() throws Exception {
        /* Given */
        PowerMockito.doReturn(500).when(childMock, "foo");
        /* When */
        childMock.boo();
        /* Then */
        Mockito.verify(childMock, Mockito.times(1)).boo();
        Mockito.verify(childMock, Mockito.times(1)).foo();
    }

    @After
    public void after() {
        Mockito.reset(childMock);
    }
}

当我运行它时,出现了这个错误。
Wanted but not invoked:
child.foo();
-> at com.test.ChildTest.shouldInvokeProtectedMockedMethod(ChildTest.java:36)

However, there were other interactions with this mock:
child.boo();
-> at com.test.ChildTest.shouldInvokeProtectedMockedMethod(ChildTest.java:33)

我做错了什么?

如果你只调用 foo 而不是 super.foo 会发生什么?我期望的是相同的行为,但当你开始搞字节码时,奇怪的事情可能会发生。 - Dave Newton
1
通过对Child进行嘲笑,您的boo方法是一种模拟实现,它实际上不会调用foo。我认为您想要的是一个Spy。 - Sotirios Delimanolis
@SotiriosDelimanolis 是的。 - JohnWinter
如果你想把它变成一个间谍,而不是用@Mock注释childMock,请使用@Spy进行注释。这将在对象上调用所有真实方法,但当你使用when()覆盖响应时,它将返回模拟的响应。 - Tim van der Lippe
我可能错了,但你只需告诉 Mockito 在 boo 上``callTheRealMethod` 就可以了吗? - BretC
你为什么要这样做呢?部分模拟是一个非常糟糕的想法。你能解释一下你试图解决的问题是什么吗?也许通过这种方式,我们可以找到如何在不进行可怕的黑客攻击的情况下帮助你的方法? - Marcin Grzejszczak
2个回答

0

如果你想检查foo()方法是否真的被调用了,你既不需要Mockito,也不需要PowerMockito。

捕获运行时异常会告诉你foo()方法已经被调用了。

package foo.bar;

import org.junit.Test;

public class ChildTest {

    /**
     * child.boo() calls super.foo(), then throws a RuntimeException.
     */
    @Test(expected = RuntimeException.class)
    public void shouldInvokeProtectedMethod() {
        Child child = new Child();
        child.boo();
    }
}

0
尝试像这样做:

@Test
public void shouldInvokeProtectedMockedMethod() throws Exception {
    int expected = 1;
    Child childMock = mock(Child.class);
    when(childMock.foo()).thenReturn(expected);
    when(childMock.boo()).thenCallRealMethod();

    childMock.boo();
    org.mockito.Mockito.verify(childMock, org.mockito.Mockito.times(1)).boo();
    org.mockito.Mockito.verify(childMock, org.mockito.Mockito.times(1)).foo();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接