使用EasyMock和PowerMock捕获私有方法参数

时间:2012-08-07 17:23:25

标签: java capture easymock powermock private-methods

对于公共方法调用,EasyMock的capture()允许您拦截&检查传递给方法的参数。对于私有方法调用,PowerMock的expectPrivate允许您模拟私有方法调用。

有没有办法以某种方式组合这些并获取传递给私有方法调用的参数?例如:

public class Program
{
    public FancyReturnType PublicMethod()
    {
        ArbitraryType localInstance = new ArbitraryType();
        localInstance.setFoo(somePrivateHelperMethod());
        localInstance.setBar(increasinglyComplexMagic());

        long aLongValue  = 11235L;
        // more variables, more work

        SomeType worker = privateHelperToIntercept(localInstance, aLongValue, otherVariables);

        if (worker.something)
        {
            return retVal.aFancyReturnType;
        }
        else
        {
            return retVal.anotherFancyReturnType;
        }
    }
}

在这种情况下,我想检查localInstance调用消耗的privateHelperToIntercept()对象。

我发现了很多模拟私有方法调用的例子; PowerMock的expectPrivate(partiallyMockedObject, "nameOfPrivateMethod", arg1, arg2)效果很好。我还找到了拦截​​传递给公共方法调用的参数的例子; Capture<Type> myTestCapture = new Capture<Type>()someMockedObject.PublicMethod(capture(myTestCapture))相结合。

不幸的是,我既不能让两者一起工作,也不能找到合并它们的例子。有没有人看到这样做的方法?

FWIW,我怀疑Mockito可以做到这一点,但它没有包含在我们的源/构建/测试系统中。如果可能的话,我想避免在我们的系统中支持新库的过程。

2 个答案:

答案 0 :(得分:1)

如果您询问如何获取对localInstance的引用,那么以下代码就足够了。

@PrepareForTest(Program.class)
public class Test {
    @Test
    public void testMethod() {
        ArbitraryType passedLocalInstance = new ArbitraryType();
        PowerMock.expectNew(ArbitraryType.class).andReturn(passedLocalInstance );

        //remainder of the test method

        assertEquals(14.2, passedLocalInstance .getValue());
    }
}

由于java是pass-by-reference,passLocalInstance将是传递给方法调用的参数。这回答了你的问题吗?

答案 1 :(得分:0)

任何类型的

new都只是一种静态方法。以同样的方式处理它...将它包装在一个方法中,将方法存根。在这种情况下,您希望在测试中返回一个模拟,然后您可以测试与该对象的所有交互(并在您正在创建的对象中的代码中删除测试中的依赖项,这应该具有它自己的测试)

public Program {

    // your above code up to object creation
    ArbitraryType localInstance = createArbitraryType();
    // rest of your above code here


  ArbitraryType createArbitraryType() {
    return new ArbitraryType();
  }
}

在你的考试中......

public class MyTest {
  TestableProgram extends Program {
    @Override 
    ArbitraryType createArbitraryType() {
      return this.arbitraryTypeMock; 
    }
  }

  private ArbitraryType arbitraryTypeMock;
  private TestableMyClass objectToTest = new TestableProgram();

  // rest of your tests...

}

考虑到你的约束,我就是这样做的。

如果可以稍微改变你的约束我放松私有方法,我通常不使用私有支持包默认使测试更容易。如果您的包中的人员行为不端,通常您的代码如此私密,无论如何主要是保护您自己。 (但我知道这不是你提出的问题的有效答案......)。