【问题标题】:Mock inherited protected method模拟继承的受保护方法
【发布时间】:2016-03-17 12:34:34
【问题描述】:

我这里有我的问题的简化版本。 A 类有一个受保护的方法。 B 类继承了这个方法。

public class A{
    protected String getString(){
        //some Code
    }
}


public class B extends A{
    public void doSomething(){
        //someCode
        String result = getString();
    }
}

我现在用 Mockito 编写一个单元测试,它在另一个包测试中,我想测试 doSomething() 方法。为此,我需要模拟 getString() 调用。由于该方法受到保护并且我的测试类位于不同的包中,因此我不能使用doReturn(...).when(classUnderTest).getString()。问题是,我在监视 B 类。所以我不能使用mock(new B(), Mockito.CALLS_REAL_METHODS)

我尝试通过反射获取受保护的方法:

Method getString = classUnderTest.getClass().getDeclaredMethod("getString");
getString.setAccessible(true);

但我不知道如何在doReturn() 中使用它。

【问题讨论】:

  • 为什么你要测试的东西和你测试的包不在同一个包里?这可能是您要纠正的第一件事。

标签: java unit-testing junit mockito


【解决方案1】:

您可以使用“覆盖和子类”

B b = new B() {
  @Override
  protected String getString() {
    return "FAKE VALUE FOR TESTING PURPOSES";
  };
};

【讨论】:

【解决方案2】:

可能有一种更简洁的方法,但这里是......

  1. 为“A”创建一个模拟
  2. 创建另一个扩展 B 并覆盖方法的类
  3. 让被覆盖的方法调用模拟

例如...

private A partialMock;
private B classUnderTest;

@Before
public void setup() {
    partialMock = mock(A.class);
    classUnderTest = new B() {
        @Override
        protected String getString() {
            return partialMock.getString();
        }
    };
}

@Test
public void shouldDoSomething() {

    when(partialMock.toString()).thenReturn("[THE MOCKED RESPONSE]");

    classUnderTest.doSomething();

    // ...verify stuff...
}

显然你甚至不需要使用模拟,你可以直接从被覆盖的方法中返回一些东西。

【讨论】:

【解决方案3】:

使用doReturn() 和Junit5 的ReflectionSupport 对我有用。

[注意:我在 Mockito 3.12.4 上测试过]

var a = spy(new A);
ReflectionSupport.invokeMethod(
        a.getClass().getSuperclass().getDeclaredMethod("getString"),
        doReturn("FAKE VALUE FOR TESTING PURPOSES").when(a));

【讨论】:

    猜你喜欢
    • 2015-03-26
    • 2020-09-09
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 2016-09-04
    • 2013-04-26
    • 2019-02-10
    相关资源
    最近更新 更多