如何模拟受保护的第三方代码方法

时间:2013-01-31 13:39:01

标签: java mocking mockito

使用Mockito我想模拟一个类的属性,以便我可以验证输出

public class MyClass extends ThirdPartyFramework {
  Output goesHere;

  @Override
  protected setup(){
    goesHere = new Output();
  }

  //...      
}

public abstract class ThirdPartyFramework {
  protected setup(){...}
  //...
}

我需要注入一个Output类的模拟,这样我就可以验证我的代码是否写了正确的输出。

  • 但我不能只@InjectMock,因为调用了setup()方法 运行中期并覆盖我的注射。

  • 我不能在MyClass中公开设置,因为我正在使用测试代码 with是通用的,需要适用于所有子类 ThirdPartyFramework,因此我只提及ThirdPartyFramework,意味着setup()受到保护。

3 个答案:

答案 0 :(得分:1)

你是否参加了Mockito?我问,因为Mockito FAQ Mockito FAQ声明它不支持模拟静态方法,我想在这种情况下你需要设置方法来创建模拟而不是真正的输出。

我已经将PowerMock用于类似的场景:

whenNew(NewInstanceClass.class).withArguments(any()).thenReturn(mockObject);

表示每次创建NewInstanceClass时都会返回我的mockObject,无论使用什么构造函数参数以及谁在什么时候构造NewInstanceClass。

在PowerMock文档中,我还发现了以下示例:

PowerMock.expectNew(NewInstanceClass.class).andReturn(mockObject)

实际上你可以使用它,即使你被Mockito绑定,PowerMock contains helpers for Mockito也可以解决这个问题,让你可以使用Mockito进行所有测试,而PowerMock可以模拟构建对象。像这样:

whenNew(Output.class).withNoArguments().thenReturn(yourOutputMock);

答案 1 :(得分:1)

我最终通过包装ThirdPartyFramework并将该类放在与ThirdPartyFramework类相同的包中来解决此问题。

这样我可以用Mockito模拟受保护的方法。然后我能够使用@InjectMock注入Output对象的模拟,并通过该模拟控制其方法调用。

答案 2 :(得分:0)

如何为“goHere”添加一个setter,然后进行setup()检查,如果为null,则只更改goHere的值。这样,您可以在测试中注入一个不会被覆盖的值。类似的东西:

protected void setGoesHere( Output output ){
    goesHere = output;
} 

@Override
protected void setup(){
    if(goesHere != null) goesHere = new Output();
}

希望这有帮助。