Android单元测试类的“private static final”成员将值更改为null

时间:2012-03-03 19:05:29

标签: java android junit

我在Android项目中有一个JUnit测试用例,其中包含如下代码:

private static final URI TEST_RESOURCE_URL = TasksService.TASKLIST_RESOURCELIST_URL.resolve("task/test.task");

public void setUp () {
    Log.i("Test", "TEST_RESOURCE_URL=" + TEST_RESOURCE_URL);
}

此测试类有多个测试方法,其中一些参考(但不尝试修改)此常量的值。但是,当我运行这些测试(Android 2.2.2)时,所有这些测试但第一个测试失败了,logcat向我展示了这个:

03-03 18:56:41.791: I/Test(12008): TEST_RESOURCE_URL=http://apate.meridiandigital.net/tasks/task/test.task
03-03 18:56:42.101: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.131: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.151: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.281: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.311: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.341: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.361: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.391: I/Test(12008): TEST_RESOURCE_URL=null
03-03 18:56:42.391: I/Test(12008): TEST_RESOURCE_URL=null

静态最终字段如何改变这样的值?我该如何防止这种情况发生?还有其他可能发生的情况吗?

---编辑1

我现在已经将代码修改为一个可以包含在其中的较小示例。见下文:

public class MyService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}


public class StaticFinalTest extends ServiceTestCase<MyService> {
    public StaticFinalTest() {
        super(MyService.class);
    }

    public static final Object CONST2 = new Object();

    public void testA ()
    {
        assertNotNull (CONST2);
    }

    public void testB ()
    {
        assertNotNull (CONST2);
    }
}

当此测试运行时,testA通过但testB失败。如果testA被注释掉,testB就会通过。

它是ServiceTestCase似乎很重要。标准的JUnit TestCase不会导致问题。如果'CONST2'是一个String,则两个测试都按预期传递。任何其他参考类型似乎都会重现这个问题。

3 个答案:

答案 0 :(得分:7)

AndroidTestCase中的每次测试后,scrubClass似乎都使用反射将所有非原始字段设置为null。它不会检查字段是静态的还是最终的,因此这似乎是问题的根源。

要解决此问题,请将字段更改为非最终字段并将其设置在setUp内。另外,请务必将super.setUp()作为setUp的第一行,以确保测试用例已正确初始化。

答案 1 :(得分:1)

垃圾收集器是否有可能摆脱它,因为它无法知道你还在使用JUnit访问该对象?

也许你应该创建一个最初设置值的方法。不要忘记使用@Begin对其进行注释,以确保正确初始化此变量。

无论如何,在测试用例中,您不应该假设先前的操作成功。 JUnit任务中所需的环境应该每次都从零开始构建。

问候

答案 2 :(得分:0)

如果它不是范围问题,您是否可能将引用的值清空。

private static final URI TEST_RESOURCE_URL = TasksService.TASKLIST_RESOURCELIST_URL.resolve("task/test.task");

因此,如果TasksService发生更改,或者对resolve()的调用失败,则可以执行此操作。