1

我只需右键单击该项目并使用 Android 框架作为 Junit Test 运行 - 该项目有 3 个文件

基类

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.preference.PreferenceManager;
import android.test.AndroidTestCase;

public class AccessPreferencesTest extends AndroidTestCase {

    static Context ctx;
    static SharedPreferences prefs;
    Editor e;
    static final boolean DEFAULT_BOOLEAN = true;
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        ctx = getContext();
        prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
        e = prefs.edit();
    }
}

抛出的文件...

public final class AccessPreferencesNullValuesTest extends
        AccessPreferencesTest {

    public void testNullBollean() {
        prefs.getString("BOOLEAN_KEY", "DEFAULT_STRING");
    }
}

...如果我testPutNullBoolean()从这个文件中删除

import gr.uoa.di.android.helpers.AccessPreferences;

public final class AccessPreferencesBooleanTest extends AccessPreferencesTest {

    public void testPutNullBoolean() {
        AccessPreferences.put(ctx, "BOOLEAN_KEY", null);
        Boolean b = AccessPreferences.get(ctx, "BOOLEAN_KEY", null);
        assertEquals(null, b);
    }

    public void testPutBoolean() {
        AccessPreferences.put(ctx, "BOOLEAN_KEY", DEFAULT_BOOLEAN);
        boolean b = AccessPreferences.get(ctx, "BOOLEAN_KEY", null);
        assertEquals(DEFAULT_BOOLEAN, b);
    }
}

gr.uoa.di.android.helpers.AccessPreferences (完全alpha,所以不要开枪)

我的启动器

不用说花了一整天的时间才把它减少到这 3 个文件。

所以如果我有testPutNullBoolean

在此处输入图像描述

而如果我删除它:

在此处输入图像描述

“故障跟踪”显示为:

java.lang.ClassCastException: java.lang.Boolean
at android.app.ContextImpl$SharedPreferencesImpl.getString(ContextImpl.java:2699)
at gr.uoa.di.android.helpers.test.AccessPreferencesNullValuesTest.testNullBollean(
    AccessPreferencesNullValuesTest.java:7)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(
    InstrumentationTestRunner.java:520)
at android.app.Instrumentation$InstrumentationThread.run(
    Instrumentation.java:1447)

我不介意 CCE(这又是一个非常精简的测试版本 + 一个 WIP)——我不明白为什么测试是相关的。刚开始测试,所以那里可能有一个明显的错误,但我现在看到它真的很头晕:)

4

1 回答 1

0

好吧,我是个菜鸟:

public final class AccessPreferences {

    private static SharedPreferences prefs;

    private static SharedPreferences getPrefs(Context ctx) {
        SharedPreferences result = prefs;
        if (result == null)
            synchronized (AccessPreferences.class) {
                result = prefs;
                if (result == null) {
                    result = prefs = PreferenceManager
                        .getDefaultSharedPreferences(ctx);
                }
            }
        return result;
    }

    public static <T> void put(final Context ctx, final String key,
            final T value) {
        final Editor ed = getPrefs(ctx).edit();
        if (value == null) {
            ed.putString(key, null); // this was called in testPutNullBoolean()
            // **nulling** the boolean I put into prefs with testPutBoolean()
            //  - which run earlier (they run alphabetically (?) - not in the 
            // order they are declared anyway). So prefs.getString() found
            // null and did not throw - whereas if I deleted testPutNullBoolean()
            // it found a Boolean...
        }
        else if (value instanceof Boolean) ed.putBoolean(key, (Boolean) value); 
        //...
        ed.commit();
    }
    //...
}

所以我缺少的是在我setUp() 的同一个 ctx 被返回

//AccessPreferencesTest

static Context ctx;

@Override
protected void setUp() throws Exception {
    super.setUp();
    ctx = getContext(); // here
    // ...
}

所以仅仅将 prefs 设置为 null 是不够的——我必须明确地清除它们。

//AccessPreferencesTest

static SharedPreferences prefs; Editor e; // set up in setUp()

@Override
protected void setUp() throws Exception {
    super.setUp();
    ctx = getContext();
    prefs = PreferenceManager.getDefaultSharedPreferences(ctx);
    e = prefs.edit();
    }

@Override
protected void tearDown() throws Exception {
    // Field f = AccessPreferences.class.getDeclaredField("prefs");
    // f.setAccessible(true);
    // // f.set(null, null); // NO USE
    // final SharedPreferences sp = (SharedPreferences) f.get(null);
    // if (sp != null) sp.edit().clear().commit();
    // I only have to clear the preferences via an editor - the
    // SharedPreferences are a singleton in the context of a single Context
    // so no need to access them via AccessPreferences and no need to
    // nullify the field in AccessPreferences [ie call f.set(null, null)] -
    // as the reference to the singleton stays valid - apparently
    if (ed != null) ed.clear().commit();
    super.tearDown();
}

如果getContext()明确说明返回相同的 ctx 会有所帮助 - 不幸的是,根本没有文档

于 2013-11-04T17:45:53.760 回答