模拟静态 class
Mocking static class
我在 class 中有一个方法可以实例化静态 class 实例并对其调用操作。
public class SomeClass {
public void someMethod() {
MyClass.MyStaticClass myStaticClassInstance =
new MyClass.MyStaticClass( arg1, arg2, arg3 );
myStaticClassInstance.callSomeMethod();
}
}
public class MyClass {
public static class MyStaticClass {
public MyStaticClass( Object arg1, Object arg2, Object arg3 ) {
}
public void callSomeMethod() {
}
}
}
如何模拟静态 class 实例化,以便我可以模拟 callSomeMethod()
而无需通过静态 class 构造函数?
您可以使用 PowerMock
通过模拟静态内部 class 的实例化来做到这一点。这可以通过准备 class 来完成,该 class 实际上会实例化您的静态内部 class,因此这里将是 class,您在其中定义了方法 someMethod()
。
假设 someMethod()
定义到 class MyOtherClass
和 returns 什么都没有,你的测试 class 将是这样的:
@RunWith(PowerMockRunner.class) // The runner of PowerMock
@PrepareForTest(MyOtherClass.class) // the class to prepare
public class MyClassTest {
@Test
public void test() throws Exception {
// The mock of your static inner class to return
MyClass.MyStaticClass mock = Mockito.mock(MyClass.MyStaticClass.class);
// Mock the call of callSomeMethod()
PowerMockito.doAnswer(
new Answer<Void>() {
@Override
public Void answer(final InvocationOnMock invocation) throws Throwable {
// Do something here as new implementation of callSomeMethod
System.out.println("My new Answer");
return null;
}
}
).when(mock).callSomeMethod();
// Return your mock in case we instantiate MyClass.MyStaticClass in
// the prepared class with any arguments
PowerMockito.whenNew(MyClass.MyStaticClass.class)
.withArguments(Matchers.any(), Matchers.any(), Matchers.any())
.thenReturn(mock);
// The code that will call someMethod
MyOtherClass mc = new MyOtherClass();
mc.someMethod();
}
}
假设我的 class MyClass
看起来像这样:
public class MyClass {
public static class MyStaticClass {
public MyStaticClass(Object arg1, Object arg2, Object arg3) {
System.out.println("Called constructor");
}
public void callSomeMethod() {
System.out.println("callSomeMethod");
}
}
}
我的 class MyOtherClass
看起来像这样:
public class MyOtherClass {
public void someMethod() {
MyClass.MyStaticClass myStaticClassInstance = new MyClass.MyStaticClass(
new Object(), new Object(), new Object()
);
myStaticClassInstance.callSomeMethod();
}
}
如果我启动测试,我会得到预期的结果:
My new Answer
而不是我应该默认得到的:
Called constructor
callSomeMethod
有关 how to constructions of new objects 的更多详细信息。
我写了一个更简单的工具来模拟通常 'non-mockable' 在 https://github.com/iirekm/misc/tree/master/ajmock
的东西
您的代码可以如下所示:
```
public class MyClassTest {
@Test
public void test() throws Exception {
MyClass.MyStaticClass mock = Mockito.mock(MyClass.MyStaticClass.class);
when(() -> mock.callSomeMethod()).thenAnswer(() -> ...);
when(() -> new MyClass.MyStaticClass(any(), any(), any())).thenReturn(mock);
// The code that will call someMethod
MyOtherClass mc = new MyOtherClass();
mc.someMethod();
}
}
```
我在 class 中有一个方法可以实例化静态 class 实例并对其调用操作。
public class SomeClass {
public void someMethod() {
MyClass.MyStaticClass myStaticClassInstance =
new MyClass.MyStaticClass( arg1, arg2, arg3 );
myStaticClassInstance.callSomeMethod();
}
}
public class MyClass {
public static class MyStaticClass {
public MyStaticClass( Object arg1, Object arg2, Object arg3 ) {
}
public void callSomeMethod() {
}
}
}
如何模拟静态 class 实例化,以便我可以模拟 callSomeMethod()
而无需通过静态 class 构造函数?
您可以使用 PowerMock
通过模拟静态内部 class 的实例化来做到这一点。这可以通过准备 class 来完成,该 class 实际上会实例化您的静态内部 class,因此这里将是 class,您在其中定义了方法 someMethod()
。
假设 someMethod()
定义到 class MyOtherClass
和 returns 什么都没有,你的测试 class 将是这样的:
@RunWith(PowerMockRunner.class) // The runner of PowerMock
@PrepareForTest(MyOtherClass.class) // the class to prepare
public class MyClassTest {
@Test
public void test() throws Exception {
// The mock of your static inner class to return
MyClass.MyStaticClass mock = Mockito.mock(MyClass.MyStaticClass.class);
// Mock the call of callSomeMethod()
PowerMockito.doAnswer(
new Answer<Void>() {
@Override
public Void answer(final InvocationOnMock invocation) throws Throwable {
// Do something here as new implementation of callSomeMethod
System.out.println("My new Answer");
return null;
}
}
).when(mock).callSomeMethod();
// Return your mock in case we instantiate MyClass.MyStaticClass in
// the prepared class with any arguments
PowerMockito.whenNew(MyClass.MyStaticClass.class)
.withArguments(Matchers.any(), Matchers.any(), Matchers.any())
.thenReturn(mock);
// The code that will call someMethod
MyOtherClass mc = new MyOtherClass();
mc.someMethod();
}
}
假设我的 class MyClass
看起来像这样:
public class MyClass {
public static class MyStaticClass {
public MyStaticClass(Object arg1, Object arg2, Object arg3) {
System.out.println("Called constructor");
}
public void callSomeMethod() {
System.out.println("callSomeMethod");
}
}
}
我的 class MyOtherClass
看起来像这样:
public class MyOtherClass {
public void someMethod() {
MyClass.MyStaticClass myStaticClassInstance = new MyClass.MyStaticClass(
new Object(), new Object(), new Object()
);
myStaticClassInstance.callSomeMethod();
}
}
如果我启动测试,我会得到预期的结果:
My new Answer
而不是我应该默认得到的:
Called constructor
callSomeMethod
有关 how to constructions of new objects 的更多详细信息。
我写了一个更简单的工具来模拟通常 'non-mockable' 在 https://github.com/iirekm/misc/tree/master/ajmock
的东西您的代码可以如下所示:
``` public class MyClassTest {
@Test
public void test() throws Exception {
MyClass.MyStaticClass mock = Mockito.mock(MyClass.MyStaticClass.class);
when(() -> mock.callSomeMethod()).thenAnswer(() -> ...);
when(() -> new MyClass.MyStaticClass(any(), any(), any())).thenReturn(mock);
// The code that will call someMethod
MyOtherClass mc = new MyOtherClass();
mc.someMethod();
}
}
```