当从其他方法调用静态方法时使用 powermockito 模拟静态
Mock static using powermockito when the static method is called in from some other method
代码示例:
public class A{
public static B connectA(){
String new = "java";
B b = new B("new");
return b;
}
public void A(){
B b = connectA();
}
}
public class B{
public B(String A){
methodB(new);
}
public static String methodB(String new){
return new;
}
}
所以,现在如果我正在测试方法 "A",:
- 当它调用 "connectA() method" 时,我希望它成为 return 我想要的模拟对象
或
- 当调用 "new B" 时,我希望它成为 return 我想要的模拟对象
如果 connectA() 方法不是静态的,它可以工作,但是如果它是静态的,我不知道如何使用 powermockito 和 mockito 使它工作
所以测试 class 会是这样的:
@RunWith(PowerMockRunner.class)
@PrepareForTest({A.class,B.class})
public class ATest(){
public void testMethodA(){
PowerMockito.whenNew(B.class).withAnyArguments().thenReturn(BMock);
A a = new A();
a.A();
}
}
其中 BMock 是我创建的任何对象!
任何可能的解决方案?
尝试添加
PowerMockito.mockStatic(A.class);
PowerMockito.mockStatic(B.class);
但我会重构代码并使用 com.google.inject.Provider 创建 B class 的实例。模拟它很容易,您不需要 PowerMockito。
更新。
这段代码对我来说是正确的(我在 class A 中添加了 getter)
package main;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.mockito.Mockito;
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
@PrepareForTest({A.class,B.class})
public class ATests{
@Test
public void testMethodA() throws Exception{
B BMock = Mockito.mock(B.class);
PowerMockito.whenNew(B.class).withAnyArguments().thenReturn(BMock);
A a = new A();
Assert.assertEquals(BMock, a.getB());
}
}
根据喷油器。
请参阅参考 https://github.com/google/guice/wiki/InjectingProviders
很难理解你想要什么以及你的 class 中的逻辑是什么。所以只有你知道你的业务规则和在哪里注入。相反,您可以使用工厂提供者。但是有一个关于使用工厂的"holy war"。
所以答案是,
当我像这样模拟时:
PowerMockito.mockStatic(B.class);
PowerMockito.when(B.methodB).thenReturn("My mocked String");
然后这里 ("My mocked string") 是使用的对象的不同实例,或者我们可以说具有不同的对象 ID(例如:a5Gbd@ass)
但是当实际上在方法 B 的构造函数中调用该方法时,它是通过作为 "new" 传入的变量调用的,它又具有不同的对象 ID(如:affac@das),所以powermockito 认为现在在构造函数中调用的方法和我们在模拟它时引用的方法是不同的。
这就是为什么它被称为 powermockito 的限制之一。
但我有一个解决方法,如果您能够以某种方式在两个地方传递相同的对象实例,它就会起作用,这样 powermockito 就知道我们正在引用相同的方法。
同样,这取决于您的代码的结构,但在我的代码中我看到这是可能的,所以它有所帮助。
对我有帮助的另一件事是使用 powermockito 访问私有变量,所以如果有人需要它:
Whitebox.getInternalState(classObjectNameCreated, "variableName");
提问,有什么不明白的,我知道我不擅长!! :)
代码示例:
public class A{
public static B connectA(){
String new = "java";
B b = new B("new");
return b;
}
public void A(){
B b = connectA();
}
}
public class B{
public B(String A){
methodB(new);
}
public static String methodB(String new){
return new;
}
}
所以,现在如果我正在测试方法 "A",:
- 当它调用 "connectA() method" 时,我希望它成为 return 我想要的模拟对象
或
- 当调用 "new B" 时,我希望它成为 return 我想要的模拟对象
如果 connectA() 方法不是静态的,它可以工作,但是如果它是静态的,我不知道如何使用 powermockito 和 mockito 使它工作
所以测试 class 会是这样的:
@RunWith(PowerMockRunner.class)
@PrepareForTest({A.class,B.class})
public class ATest(){
public void testMethodA(){
PowerMockito.whenNew(B.class).withAnyArguments().thenReturn(BMock);
A a = new A();
a.A();
}
}
其中 BMock 是我创建的任何对象!
任何可能的解决方案?
尝试添加
PowerMockito.mockStatic(A.class);
PowerMockito.mockStatic(B.class);
但我会重构代码并使用 com.google.inject.Provider 创建 B class 的实例。模拟它很容易,您不需要 PowerMockito。
更新。
这段代码对我来说是正确的(我在 class A 中添加了 getter)
package main;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.mockito.Mockito;
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
@PrepareForTest({A.class,B.class})
public class ATests{
@Test
public void testMethodA() throws Exception{
B BMock = Mockito.mock(B.class);
PowerMockito.whenNew(B.class).withAnyArguments().thenReturn(BMock);
A a = new A();
Assert.assertEquals(BMock, a.getB());
}
}
根据喷油器。 请参阅参考 https://github.com/google/guice/wiki/InjectingProviders 很难理解你想要什么以及你的 class 中的逻辑是什么。所以只有你知道你的业务规则和在哪里注入。相反,您可以使用工厂提供者。但是有一个关于使用工厂的"holy war"。
所以答案是,
当我像这样模拟时:
PowerMockito.mockStatic(B.class);
PowerMockito.when(B.methodB).thenReturn("My mocked String");
然后这里 ("My mocked string") 是使用的对象的不同实例,或者我们可以说具有不同的对象 ID(例如:a5Gbd@ass)
但是当实际上在方法 B 的构造函数中调用该方法时,它是通过作为 "new" 传入的变量调用的,它又具有不同的对象 ID(如:affac@das),所以powermockito 认为现在在构造函数中调用的方法和我们在模拟它时引用的方法是不同的。
这就是为什么它被称为 powermockito 的限制之一。
但我有一个解决方法,如果您能够以某种方式在两个地方传递相同的对象实例,它就会起作用,这样 powermockito 就知道我们正在引用相同的方法。
同样,这取决于您的代码的结构,但在我的代码中我看到这是可能的,所以它有所帮助。
对我有帮助的另一件事是使用 powermockito 访问私有变量,所以如果有人需要它:
Whitebox.getInternalState(classObjectNameCreated, "variableName");
提问,有什么不明白的,我知道我不擅长!! :)