【问题标题】:Using PowerMockito and Mockito to test call to other artifact's method使用 PowerMock 和 Mockito 测试对其他工件方法的调用
【发布时间】:2015-04-21 15:04:56
【问题描述】:

我确信这是一个很常见的问题,但我真的无法摆脱我在模拟私有方法时遇到的这个问题,该方法在内部调用另一个方法并返回一个集合。 我正在测试的类有一个公共方法,它调用私有方法来获取 Collection 对象。我使用 PowerMock 来创建一个私有方法的间谍。

public void method1(String s)
{
     Collection<Object> list = invokePrivate()
}

private Collection<Object> invokePrivate()
{
     Wrapper wrapperObj = Factory.getInstance.getWrapper();
     Collection<Object> list = wrapperObj.callWrapperMethod(); // This always calls into real method, instead of mocked version.
     return list;
}

测试类-:

所以为了测试公共方法“method1”,我使用 PowerMockito 创建了一个间谍来监视私有方法并返回一个演示列表。

MainClass obj = new MainClass();
MainClass spy = PowerMockito.spy(obj);
PowerMockito.when(spy, method(MainClass.class, "inokePrivate"))
                            .thenReturn(list); // demo list which exists as a test class member.

上面调用私有方法,该方法又尝试调用驻留在不同工件中的 wrapperObj.callWrapperMethod() 并在那里中断,因为它在那里找不到某些实现。 所以我尝试模拟 wrapperObj.callWrapperMethod。

WrapperClass wr = new WrapperClass();
WrapperClass spy1 = PowerMockito.spy(wr);
when(spy1.callWrapperMethod()).thenReturn(list) // demo list which exists as a test class member.

再次模拟调用 callWrapperMethod() 的实际实现并在那里中断。 如何防止调用包装器方法的实际实现?

一些对我有帮助的答案-:

Mockito:How to mock method called inside another method

Testing Private method using mockito

[更新] -:正如我所做的建议那样 - :

PowerMockito.doReturn(list).when(spy1).callWrapperMethod(); // This returns me demo list successfully.

但是现在当我从 PowerMockito 调用私有方法时,控制进入 invokePrivate 方法并再次尝试调用原始 callWrapperMethod 而不是从间谍版本返回列表。

【问题讨论】:

标签: java unit-testing junit mockito powermock


【解决方案1】:

我建议不要这样做。您的私有方法应该使用静态方法检索单例工厂对象。

静态的东西打破了“简单”的嘲笑;强迫你使用“权力”嘲讽;因此,产生的问题多于解决的问题。

更改您的代码以使用依赖注入。做这样的事情:

class YourClass {
  private final Factory factory;

  public YourClass() {
     this(Factory.getInstance(); }

  YourClass(Factory theFactory) {
     this.factory = theFactory;
  ...

这将允许您在单元测试中使用第二个构造函数;为您的班级提供一个(容易模拟的)工厂对象。从而消除对 PowerMock 的全部需求。

长话短说 - 当代码难以测试时;更改代码;而不是测试。作为副作用,您正在提高代码的质量 - 因为您放松了对该单例对象的硬依赖。

为了完整起见:我还建议避免“破坏”得墨忒耳法则(http://en.wikipedia.org/wiki/Law_of_Demeter):如果您的课程需要包装器;那么它应该包含一个包装对象;如果它需要那个工厂;那么它应该保存一个工厂对象。但是你不应该持有一个对象......从那里检索另一个对象,在第二个对象上运行某些东西。如您所见 - 这样做会导致您面临的问题。

【讨论】:

  • 使用上面的方法,我仍然需要调用 wrapperObj.callWrapperMethod() ,因为它在不同的工件中,我不想调用原始方法。在调用公共方法时,它总是调用原始的 callWrapperMethod 而不是模拟对象。
  • 是什么阻止了你的模拟工厂返回一个模拟的包装器?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多