从 J 单元测试用例调用时 getApplicationContext() 返回 null

问题描述 投票:0回答:2

我必须对扩展到服务的 Android 类进行 J 单元测试。

我的源代码中有以下几行:-

    public class AService extends Service{

        public AService () {
            super("AService");
        }
    ....
    ...
    @Override
        public void onStart(Intent intent, int startId) {
            Log.d(TAG, "onStart");
            LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(
                BroadCastReceiver_Object,
                new IntentFilter("any String"));
            super.onStart(intent, startId);
        }
...
...
}

我需要对上面的类进行J单元测试。我写的测试类如下:-

public class AServiceTest extends AndroidTestCase {

    AService AServiceobj;

    /*
     * (non-Javadoc)
     * 
     * @see junit.framework.TestCase#setUp()
     */
    protected void setUp() throws Exception {
        super.setUp();
        AServiceobj = new AService();
    }

    /*
     * (non-Javadoc)
     * 
     * @see junit.framework.TestCase#tearDown()
     */
    protected void tearDown() throws Exception {
        super.tearDown();
    }


    public void testonStart() {
        Intent intent = new Intent();
        int startId = 0;
        AServiceobj.onStart(intent, startId);
    }
}

但是上面的 TC 失败了,它在“getApplicationContext()”处给出了空指针异常。 我该如何解决这个问题。

android junit android-service
2个回答
1
投票

对于测试服务,您可以延长

ServiceTestCase

您还可以在开始服务之前使用

setApplication()
或/和
setContext()
与模拟上下文一起使用。

请参阅本文了解更多信息http://developer.android.com/tools/testing/service_testing.html

更新:我添加了如何使用 ServiceTestCase 的简短示例。

MyService 只是简单的服务,它从应用程序上下文中读取 processName (因此应用程序上下文必须存在。这只是为了确认示例有效,否则会出现与您的情况相同的问题 NullPointerException)。

public class MyService extends Service {
    public MyService() {
    }

    private String procName;

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);

        Context ctx = getApplicationContext();

        procName = ctx.getApplicationInfo().processName;
    }

    public String getProcName(){
        return this.procName;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new LocalBinder();
    }

    public class LocalBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }
}

这是服务测试:

public class MyServiceTest extends ServiceTestCase<MyService> {

    public MyServiceTest() {
        super(MyService.class);
    }

    public void testProcName(){
        // here we take and use context from ServiceTestCase.getContext()
        Intent intent = new Intent(getContext(), MyService.class);
        startService(intent);

        assertNotNull(getService().getProcName());
    }
}

0
投票

在测试依赖于

Context
的类时,请记住Android框架在测试环境中并不完全可用。在这种情况下,您有两种解决方案:

  1. Context
    传递到类构造函数中。
  2. 模拟
    getAppContext()
    方法(假设它是在您的 App 类中定义的)。

这是测试此类案例的模板:

public class ServiceTest {

    @Mock
    Context mockContext;

    // To hold the static mock reference
    private MockedStatic<App> appMock;


    @Before
    public void setUp() {
        openMocks(this);
        // Mock the static App.getAppContext() method
        appMock = Mockito.mockStatic(App.class);
        when(App.getAppContext()).thenReturn(mockContext);

        // ... 
    }

    @After
    public void tearDown() {
        // Ensure the static mock is closed after each test
        appMock.close();
    }
   
    // test cases...


© www.soinside.com 2019 - 2024. All rights reserved.