PowerMockito.whenNew没有嘲笑子类是否没有任何构造函数

时间:2017-12-13 08:59:44

标签: java unit-testing testing mocking powermockito

我有一个名为MyXStream的内部私有类,它扩展了com.thoughtworks.xstream.XStream

OuterClass.java

public class OuterClass {
  private class MyXStream extends XStream {
    @Override
    protected MapperWrapper wrapMapper(MapperWrapper next) {
      // implementation details
    }
  }

  public void myMethod() {
    XStream myXStream = new MyXStream();
  }
}

我使用的测试用例

OuterClassTest.java

Class myXStreamClass = Whitebox.getInnerClassType(OuterClass.class, "MyXStream");
XStream xStream = (XStream) PowerMockito.mock(myXStreamClass);
PowerMockito.whenNew(myXStreamClass).withNoArguments().thenReturn(xStream);

它不起作用。 myXStream为null并导致NullPointerException。然后我尝试向MyXStream添加一个构造函数,看看发生了什么:

public class OuterClass {
  private class MyXStream extends XStream {
    public MyXStream() {
      // some debug statements
    }

    @Override
    protected MapperWrapper wrapMapper(MapperWrapper next) {
      // implementation details
    }
  }
}

测试案例有效。

我也可以将withNoArguments()替换为withAnyArguments(),这也有效。像这样:

OuterClassTest.java

Class myXStreamClass = Whitebox.getInnerClassType(OuterClass.class, "MyXStream");
XStream xStream = (XStream) PowerMockito.mock(myXStreamClass);
PowerMockito.whenNew(myXStreamClass).withAnyArguments().thenReturn(xStream);

我只是想知道为什么我不能只使用withNoArguments()如果我没有指定任何构造函数? Java编译器不应该为我创建一个空的吗?它们之间有什么区别?

更新

最小,完整且可验证的示例

OuterClass.java

package test;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.mapper.MapperWrapper;

public class OuterClass {
    private class MyXStream extends XStream {
        @Override
        protected MapperWrapper wrapMapper(MapperWrapper next) {
            return null;
        }
    }

    public void myMethod() {
        XStream myXStream = new MyXStream();
        myXStream.fromXML("xml");
    }
}

OuterClassTest.java

package test;

import com.thoughtworks.xstream.XStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest({
        OuterClass.class
})
public class OuterClassTest {
    private OuterClass outerClass;

    @Before
    public void setUp() {
        outerClass = PowerMockito.spy(new OuterClass());
    }

    @Test
    public void myMethod() throws Exception {
        Class myXStreamClass = Whitebox.getInnerClassType(OuterClass.class, "MyXStream");
        XStream xStream = (XStream) PowerMockito.mock(myXStreamClass);

        // withAnyArguments() worked
        // PowerMockito.whenNew(myXStreamClass).withAnyArguments().thenReturn(xStream);

        // withNoArguments() will cause java.lang.NullPointerException
        PowerMockito.whenNew(myXStreamClass).withNoArguments().thenReturn(xStream);

        outerClass.myMethod();

        Mockito.verify(xStream, Mockito.times(1)).fromXML("xml");
    }

}

我意识到直接在代码中调用new不适合测试,但我发现PowerMockito可以模拟新实例并且有一些奇怪的行为并且不知道原因。

  • 为什么withNoArguments()即使我的new语句不起作用也不会传递任何参数?

  • 为什么在MyXStream中添加空构造函数可以解决这个问题?

0 个答案:

没有答案