Robolectric&测试startActivityForResult

时间:2013-01-23 14:29:54

标签: android testing android-intent assert robolectric

我的Robolectric单元测试遇到了麻烦。

当侦听器使用方法startActivity( Intent )

时,我可以毫无疑问断言点击开始了新活动

但是当使用方法startActivityForResult(Intent, int)启动新活动时,Robolectric似乎有问题:在代码中放置一些中断让我发现活动没有启动(只是更改方法{{1使断言传递)。

这是正常的吗?很遗憾,因为我的应用的第一个活动使用了startActivity( Intent )

是否有人设法通过这种方式启动活动进行测试?

感谢您的帮助..

2 个答案:

答案 0 :(得分:3)

简短回答你的问题是,由于Robolectric将Android类转换为在JVM中执行的代码的方式,它们的许多功能都没有像你期望的那样运行。许多系统回调都不会执行,你必须依赖Robolectric在其类的Shadow实现中提供的内容。 (参见@Steven_BDawg提供的链接。)

答案很长:有可能在一个大的测试中实现这整个流程,但这不是框架的设计目标。

Robolectric和单元测试一般不用于您描述的方式。 The Unit Testing page on wikipedia声明可以将单元视为应用程序的最小可测试部分。单元测试套件应包含许多轻量级测试,其中每个测试都会隔离应用程序中的一些功能并确保其正常工作。

考虑包含两个活动A和B的基本应用程序。活动A显示有关主题的一些信息,活动B允许用户选择要在A中显示的主题。当用户从活动A移动到活动B时,B使用startActivityForResult()进行调用,并且应该使用所选主题返回A.

现在说我们要单元测试A的流程,从B获取结果并显示数据。我们可以将其分解为两个测试:

  1. 测试中的活动 - 活动A.在我们的测试中,我们将创建一个活动A的新实例。在Robolectric测试中,我们创建我们期望B返回A的Intent,并调用shadow方法{{ 1}}对于A,用结果代码OK和此Intent填充参数。在receiveResult()之后,运行您的断言。您现在知道活动A正确处理结果!
  2. 测试中的活动 - 活动B.在我们的测试中,我们将创建一个活动B的新实例,将其设置为从活动A的结果开始。在Robolectric测试中,我们将执行所有操作需要选择数据,创建我们将发回的意图,然后对意图运行断言以确保它被正确创建。
  3. 这是一个非常简单的例子。这两个步骤可能会被分解为更多的测试,因为每个单元测试应该只测试应用程序可以分解的最小功能单元。这个例子主要是为了帮助你开始考虑单元测试的方式。我发现随着我对单元测试的理解加深,我编写代码的方式也发生了变化。我试图避免以这样的方式编写方法和类,以至于它们做了太多的工作并且无法进行适当的单元测试。根据经验,易于单元测试的代码执行非常具体的操作,这在第一次阅读代码时很明显。

    最后,如果您想更进一步,模拟框架可以极大地帮助您进行单元测试。 Mockito是我过去成功的嘲弄框架。模拟框架的目的是创建您严格控制其行为的存根对象。 Mockito(或任何其他Mocking Framework)将允许您定义一个从您需要的任何类型扩展的对象,并且只实现您需要的方法。您将能够直接控制对任何这些方法调用的响应。这有助于单元测试,因为您需要的唯一真实对象是被测对象;通过模拟所有其他对象,您将更好地了解对象测试是否正常运行,因为所有其他行为都由您(测试人员)明确定义。 (是的,这确实导致了许多额外的代码,但这是一个优秀的单元测试人员的生活。但是,如前所述,随着您对单元测试的熟悉程度越来越高,您可能会发现自己编写的方法需要较少的模拟和更有利于编写测试。一些编码人员甚至会在他们编码之前编写他们的单元测试,以保持他们的代码紧密并专注于单一目的)

    希望这有帮助!

答案 1 :(得分:1)

我为你做了一些谷歌。我不知道这对你有没有帮助,但我认为这是一个好的开始! Roboelectric: Testing startActivityForResult() and onActivityResult()