我正在尝试进行一些单元测试,而我还没有真正解决过跑步者或测试课程。
最后,这是我验证它有效的方法:
public static void getData(final Context context, final Callback<MyObject> callback) {
Locale locale = context.getResources().getConfiguration().locale;
MyObjectService myService = new MyObjectService(getRequestHeaders(context), locale);
}
所以我需要一个具有资源,配置,语言环境和SharedPreferences的模拟上下文。
我尝试过PowerMockito,AndroidTestCase,AndroidTestRunner,ApplicationTestCase。我所能得到的只是一个没有任何内容的模拟上下文,或模拟资源,但我无法弄清楚如何将它们添加到模拟上下文中(基本上重新创建一个上下文)。
这是我目前的最后一次尝试(虽然我尝试过更复杂的尝试,但没有成功):
import com.myApp.android.app.shop.util.ServiceUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.modules.junit4.PowerMockRunner;
import android.content.Context;
@RunWith(PowerMockRunner.class)
public class TestLogin
{
@Test
public void test()
{
Context context = Mockito.mock(Context.class);
ServiceUtils.getData(context, dataCallback);
}
}
我得到的异常是来自getData()的NPE,因为传递的上下文没有资源。
有什么建议吗?
答案 0 :(得分:2)
Android不是一个容易模拟的系统。我也尝试使用Mockito来模拟框架,但它很快变得非常复杂。像资源和SharedPreferences这样的东西不容易模拟。这些问题已在Robolectric等第三方API中得到解决。
我建议您使用Robolectric进行Android单元测试。 Robolectric在标准VM中运行(即不需要仿真器)。 Robolectric模拟Android系统的大部分,从而最大限度地减少(但不是消除)构建模拟的需要。我发现它是Android TDD的一个非常有用的工具。
答案 1 :(得分:0)
使用Robolectric的RuntimeEnvironment
Locale locale = RuntimeEnvironment.application.getResources().getConfiguration().locale;
答案 2 :(得分:0)
作为第二个答案(可能比第一个答案更有用),我建议你从平台的依赖项中分离逻辑。
通过这种方式,您可以考虑以纯java方式对逻辑进行单元测试。
看看MVP模式。它应该有很多帮助!
在这种情况下,例如,你会移动这一行......
MyObjectService myService = new MyObjectService(getRequestHeaders(context), locale);
...在“服务”内部,它完全是由构造函数分配的纯java类,需要(在本例中)一个名为“locale”的String值和一个名为“headers”的数据结构
容易,不是吗? ;)
我的2美分:每次你需要Robolectric来测试逻辑(而不是UI)你可能会犯错误