如何在Android单元测试中模拟Bundle方法?

4

我有一个控制器类来处理Fragment的创建。就像下面这样:

public class FragmentController {

    public static Fragment newInstance(String title, int total) {
        return total > 0? MultipleDataFragment.newInstance(title, total)
            : SingleDataFragment.newInstance(title);
    }
}

public class MultipleDataFragment extends Fragment {
    public static MultipleDataFragment newInstance( String title, int total) {
        Bundle b = new Bundle();
        b.putString("title", title);
        b.putInt("total", total);
    }
}

public class SingleDataFragment extends Fragment {
    public static SingleDataFragment newInstance( String title, int total) {
        Bundle b = new Bundle();
        b.putString("title", title);
        b.putInt("total", total);
    }
}

在我的测试中(标准的Junit4测试类),我有以下代码:
@Test
public void testNewInstanceCreteMultipleData() throws Exception {
    Fragment f = FragmentController.newInstance("Hello", 5);

    assertTrue("MultipleDataFragment should be created"
        , f instanceOf MultipleDataFragment);
}

由于我没有模拟Bundle,所以我遇到了问题。

java.lang.RuntimeException: Method putString not mocked.Set

问题是我如何模拟Bundle对象,以便可以执行测试?我需要在每个类中使用静态方法来创建Bundle对象并使用它,还是有更好的方法?
欢迎提供任何相关示例。

请注意,您的getInstance()方法不完整。它们甚至没有返回语句。 - Code-Apprentice
2个回答

6
一种方法是使用强大的模拟框架,比如PowerMock,它甚至可以拦截新对象的构建。
这对你应该是可行的,但是模拟像Bundle这样的“简单”类需要一些努力-你也可以使用UnMock插件来使用真实的实现。

1
关于 Bundle 类的模拟示例,您可以查看我对非常相似问题的回答。关于 UnMock,我在使用 Bundle 时遇到了麻烦,因为在运行简化测试用例时出现了“NoSuchFieldError”错误,该错误与“mMap”有关。 - Sigbjørn
从API 21开始,Bundle扩展了BaseBundle,这就是为什么它找不到mMap的原因。不幸的是,取消模拟BaseBundle并没有帮助,因为ArrayMap现在使用JVM不包含的System.arraycopy()的非标准版本。因此,取消模拟Bundle无效。 - Erik Browne
@ErikBrowne,你的解决方案是什么? - Huteri

0
使用Unmock插件来取消模拟Bundle类。您需要在Android 4.4(unmock 'org.robolectric:android-all:4.4_r1-robolectric-1')中进行取消模拟,因为后续版本的Android引用了非标准Java方法。
您还需要保留ArrayMap和MapCollections。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接