如何从模拟上下文中获取Locale

时间:2016-01-25 19:49:54

标签: java android unit-testing junit mockito

我正在尝试进行一些单元测试,而我还没有真正解决过跑步者或测试课程。

最后,这是我验证它有效的方法:

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,因为传递的上下文没有资源。

有什么建议吗?

3 个答案:

答案 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)你可能会犯错误