java 如何android单元测试和模拟静态方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32074356/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to android unit test and mock a static method
提问by James
Hi I really hope you can help me, I feel like I've been pulling my hair out for days.
嗨,我真的希望你能帮助我,我觉得我已经把头发拉了好几天了。
I'm trying to write unit tests for a method A. Method A calls a static method B. I want to mock static method B.
我正在尝试为方法 A 编写单元测试。方法 A 调用静态方法 B。我想模拟静态方法 B。
I know this has been asked before, but I feel Android has matured since then, and there must be a way to do such a simple task without re-writing the methods I want to test.
我知道以前有人问过这个问题,但我觉得从那时起Android已经成熟了,必须有一种方法可以在不重新编写我要测试的方法的情况下完成如此简单的任务。
Here is an example, first the method I want to test:
这是一个例子,首先是我要测试的方法:
public String getUserName(Context context, HelperUtils helper) {
if(helper == null){
helper = new HelperUtils();
}
int currentUserId = helper.fetchUsernameFromInternet(context);
if (currentUserId == 1) {
return "Bob";
} else {
return "Unknown";
}
}
Next the static method I want to mock:
接下来是我要模拟的静态方法:
public class HelperUtils {
public static int fetchUsernameFromInternet(Context context) {
int userid = 0;
Log.i("HelperUtils ", "hello");
return userid;
}
}
In other languages this is so easy but I just can't make it work in Android. I've tried Mockito, but it appears static methods aren't supported
在其他语言中,这很容易,但我无法让它在 Android 中运行。我试过 Mockito,但似乎不支持静态方法
HelperUtils helper = Mockito.mock(HelperUtils.class);
Mockito.when(helper.fetchUsernameFromInternet(getContext())).thenReturn(1);
This errors
这个错误
org.mockito.exceptions.misusing.MissingMethodInvocationException
org.mockito.exceptions.misusing.MissingMethodInvocationException
I've tried Powermock but I'm not completely sure this is supported by Android. I managed to get powermock running using androidCompile in my gradle file but I get this error:
我试过 Powermock,但我不完全确定 Android 是否支持它。我设法在我的 gradle 文件中使用 androidCompile 运行 powermock 但我收到此错误:
Error:Execution failed for task ':app:dexDebugAndroidTest'. com.android.ide.common.process.ProcessException:
错误:任务 ':app:dexDebugAndroidTest' 的执行失败。com.android.ide.common.process.ProcessException:
Not to mention PowerMockito.mockStatic(HelperUtils.class);
Doesn't return anything, so I don't know what to pass into my getUsername method!
更不用说PowerMockito.mockStatic(HelperUtils.class);
不返回任何内容,所以我不知道要传递给我的 getUsername 方法!
Any help would be so very much appreciated.
任何帮助将不胜感激。
回答by iirekm
Static methods aren't related to any object - your helper.fetchUsernameFromInternet(...)
is the same (but a bit confusing) as HelperUtils.fetchUsernameFromInternet(...)
- you should even get a compiler warning due to this helper.fetchUsernameFromInternet
.
静态方法与任何对象都没有关系——你helper.fetchUsernameFromInternet(...)
是一样的(但有点混乱)HelperUtils.fetchUsernameFromInternet(...)
——你甚至应该因此得到编译器警告helper.fetchUsernameFromInternet
。
What's more, instead of Mockito.mock
to mock static methods you have to use: @RunWith(...)
, @PrepareForTest(...)
and then PowerMockito.mockStatic(...)
- complete example is here: PowerMockito mock single static method and return object
更重要的是,不是Mockito.mock
模拟静态方法,你必须使用:@RunWith(...)
,@PrepareForTest(...)
然后PowerMockito.mockStatic(...)
- 完整的例子在这里:PowerMockito mock single static method and return object
In other words - mocking static methods (and also constructors) is a bit tricky. Better solution is:
换句话说 - 模拟静态方法(以及构造函数)有点棘手。更好的解决办法是:
if you can change
HelperUtils
, make that method non-static and now you can mockHelperUtils
with the usualMockito.mock
if you can't change
HelperUtils
, create a wrapper class which delegates to the originalHelperUtils
, but doesn't havestatic
methods, and then also use usualMockito.mock
(this idea is sometimes called "don't mock types you don't own")
如果您可以更改
HelperUtils
,请将该方法设为非静态,现在您可以HelperUtils
使用通常的方法进行模拟Mockito.mock
如果你不能改变
HelperUtils
,创建一个包装类,它委托给原始的HelperUtils
,但没有static
方法,然后也使用通常的Mockito.mock
(这个想法有时被称为“不要模拟你不拥有的类型”)
回答by Hiren Patel
I did this way using PowerMockito.
我使用PowerMockito这样做。
I am using AppUtils.class
, it contains multiple static methods and functions.
我正在使用AppUtils.class
,它包含多个静态方法和函数。
Static function:
静态功能:
public static boolean isValidEmail(CharSequence target) {
return target != null && EMAIL_PATTERN.matcher(target).matches();
}
Test case:
测试用例:
@RunWith(PowerMockRunner.class)
@PrepareForTest({AppUtils.class})
public class AppUtilsTest {
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(AppUtils.class);
PowerMockito.when(AppUtils.isValidEmail(anyString())).thenCallRealMethod();
}
@Test
public void testValidEmail() {
assertTrue(AppUtils.isValidEmail("[email protected]"));
}
@Test
public void testInvalidEmail1() {
assertFalse(AppUtils.isValidEmail("[email protected]"));
}
@Test
public void testInvalidEmail2() {
assertFalse(AppUtils.isValidEmail("@email.com"));
}
}
Edit 1:
编辑1:
Add following imports:
添加以下导入:
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
Hope this would help you.
希望这会帮助你。