如何调用抽象类的私有构造函数进行模拟.

dim*_*ime 4 java reflection unit-testing easymock powermock

关于如何正确测试此代码,我遇到了一些问题.我希望能够使用Mocking框架或甚至反射来模拟对delegateForFoo的调用.但是,当我尝试通过反射或通过PowerMock执行此操作时,我会收到如下代码中所示的错误.

@Test
public void testDelegatedMethodWithPowerMock() throws Exception {

    DelegateForFoo mockedDelegateForFoo = PowerMock
            .createMock(DelegateForFoo.class);

    Foo foo = Whitebox.invokeConstructor(Foo.class, mockedDelegateForFoo);
    // org.powermock.reflect.exceptions.ConstructorNotFoundException: Failed
    // to find a constructor with parameter types: at line above.

    Constructor<Foo> fooConstructor = Foo.class
            .getDeclaredConstructor(DelegateForFoo.class);
    fooConstructor.setAccessible(true);
    Foo foo2 = fooConstructor.newInstance(mockedDelegateForFoo);
    // java.lang.InstantiationException at line above.

}
Run Code Online (Sandbox Code Playgroud)

我尽力检查以前的stackOverflow问题,但我没有看到直接解决此问题的问题.关于如何调用具体类的私有构造函数有一些答案,还有一些关于如何在抽象类上调用私有方法的答案,但在这个特定实例上没有.

我的官方问题如下:有没有办法调用抽象类的私有构造函数并传入一个模拟对象用于测试目的.

我知道通常你不应该测试私有方法等.但是在这种情况下,我想测试一个有正当理由是私有的构造函数.Bar根本没有理由知道关于委托的任何事情,如果要进行适当的封装,它应该是私有的.提前致谢.

我正在使用的代码如下.

public abstract class Foo {

    private DelegateForFoo delegateForFoo;
    private int valueToBeSetFromDelegate;

    Foo() {
        // I don't want the subclasses to do anything with this DelegateForFoo.
        // It's set through the constructor because there is a requirement that
        // Foo must have a delegateForFoo in order to be created.
        this(new DelegateForFoo());
    }

    // This Constructor is indirectly called by the subclasses. They don't know
    // anything about how it is set, or what it does.
    private Foo(DelegateForFoo delegateForFoo) {
        this.delegateForFoo = delegateForFoo;
        this.valueToBeSetFromDelegate = this.delegateForFoo.delegatedMethod();
    }

    int useTheDelegateForSomeMethod() {
        return this.delegateForFoo.delegatedMethod();
    }
}


public class DelegateForFoo {
    int delegatedMethod() {
        return 5;
    }
}



public class Bar extends Foo {
    // here, Bar doesn't care about the delegate for Foo at all. It only cares
    // that the method it is called has some implementation.
    int useDelegateForFooWithoutKnowingAboutIt() {
        return super.useTheDelegateForSomeMethod() + 10;
    }
}
Run Code Online (Sandbox Code Playgroud)

Dam*_*ash 6

您无法创建Foo类实例的原因是因为它abstract.Java中没有可以创建抽象类实例的机制.

要测试抽象类,您需要定义将扩展Foo的新类.这意味着将调用默认构造函数.