【问题标题】:Mockito tests for class with Handler带有 Handler 的类的 Mockito 测试
【发布时间】:2022-01-28 03:22:07
【问题描述】:

我是 android dev 中的新人,所以我有一个包含 viewPager 的应用程序,其中包含 2 个 UI 片段和 1 个执行操作的非 UIFragment(我使用了“setRetainInstance(true)”,它已弃用,但我必须使用它)。在这个 nonUIFragment 中,我有 Handler,它接受来自 ExecutorServices 开始的操作的消息。 但现在我的任务是用 Mockito 测试这个应用程序,我完全糊涂了。

Mentor 说“你必须模拟产生结果的操作,在一个非 UIFragment 中执行,并将其结果存储在一个集合中。”

如何看待这个测试,我无法创建 spy() 类 NonUIFragment 并使用真正的方法,因为“android.os.Looper 中的方法 getMainLooper 未模拟。” 我所有的方法都是无效的,他们不返回任何东西,我怎么能追踪这个链。

NonUIFragment.java

private NonUIToActivityInterface nonUIInterface;
    private final Map<DefOperandTags, HashMap<DefOperationTags, String>> allResultsMap
        = new HashMap<>();

 @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

//Handler pass result to here
    public void passAndSaveResult(DefOperandTags operandTag, DefOperationTags operationTag, String result) {
        allResultsMap.get(operandTag)).put(operationTag, result);
    }

private final Handler handler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(Message msg) {
            if (msg.what != null)
                passAndSaveResult(defOperandTags, defOperationTag, msg.obj.toString());
    };

OneOfOperation.java(向列表添加值)

public class AddToStartList extends Operation {

    public AddToStartList(List list, DefOperationTags operationTag) {
        super(list);
        key = operationTag;
    }

    @Override
    public void operation(Object collection) {
        ((List)collection).add(0, "123");
    }

那么,我该如何落实导师所说的呢?

【问题讨论】:

  • Mockito 提供了几种模拟事物的方法,您需要找到适合您情况的方法。例如,Mockito 有一类模拟方法,用于模拟没有返回值的方法,即 void。我认为您需要寻找如何使用 Mockito 进行 Android 开发。

标签: java android mockito handler looper


【解决方案1】:

这会很棘手,因为您的 Android 测试库 has no implementations 和静态方法通常更难以安全有效地模拟。

最近版本的 Mockito 添加了 the ability to mock static methods 而不使用像 PowerMock 这样的其他库,所以第一选择是这样的。如果可能,请在Looper::getMainLooper 上使用mockStatic 进行模拟。

另一个解决方案是添加一些间接性,给你一个测试接缝:

public class NonUIFragment extends Fragment {
  /** Visible for testing. */
  static Looper overrideLooper;

  // ...

  private final Handler handler = new Handler(
      overrideLooper != null ? overrideLooper : Looper.getMainLooper()) {
    /* ... */
  };
}

最后,如果你发现自己经常做这种模拟,你可以考虑像Robolectric 这样的库。使用 Robolectric,您可以simulate the looper with a ShadowLooper,它可以让您远程控制它,同时将 Mockito 用于您的团队编写的任何课程。例如,这将使您不必为每个测试模拟一个真实的 Looper。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多