我目前正在对图书馆进行单元测试。在某些类中,我需要在一些静态方法中将活动作为参数传递。图书馆本身不包含任何活动。我需要以某种方式获取模拟活动的实例,以便在每个单独的方法测试中使用。
我已阅读Activity Testing Tutorial和Testing Fundamentals部分。如果你要测试已经存在于待测试项目中的活动,那么它的大部分内容才有意义。但我只需要一个模拟器来做一些事情,比如在Ui线程中显示对话框和运行短任务。
实现这一目标的最快,最简单的方法是什么?我应该在我的测试项目中创建模拟活动,还为虚拟UI提供xml布局资源?
UPDATE
由于我没有找到任何自动创建模拟活动的方法,所以我决定自己提供。我在测试项目中创建了一个虚拟活动,什么都不做,并通过xml提供了一个虚拟布局。然后我将我的测试编码为ActivityInstrumentationTestCase2
:
public class LibraryTest extends ActivityInstrumentationTestCase2<MockActivity> {
public LibraryTest(String name) {
super(MockActivity.class);
}
protected void setUp() throws Exception {
super.setUp();
}
public void testAMethodFromLibrary() {
fail("Not yet implemented");
}
}
MockActivity
是我在此测试项目中创建的上述模拟活动。但是,似乎Android测试框架在启动活动时遇到了问题,并且出现了这个异常:
java.lang.RuntimeException: Exception during suite construction
at android.test.suitebuilder.TestSuiteBuilder$FailedToCreateTests.testSuiteConstructionFailed(TestSuiteBuilder.java:239)
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)
Caused by: java.lang.NullPointerException: Method name must not be null.
at java.lang.ClassCache.findMethodByName(ClassCache.java:297)
at java.lang.Class.getMethod(Class.java:985)
at android.test.suitebuilder.TestMethod.getAnnotation(TestMethod.java:60)
at android.test.suitebuilder.annotation.HasMethodAnnotation.apply(HasMethodAnnotation.java:39)
at android.test.suitebuilder.annotation.HasMethodAnnotation.apply(HasMethodAnnotation.java:30)
at com.android.internal.util.Predicates$OrPredicate.apply(Predicates.java:106)
at android.test.suitebuilder.annotation.HasAnnotation.apply(HasAnnotation.java:42)
at android.test.suitebuilder.annotation.HasAnnotation.apply(HasAnnotation.java:31)
at com.android.internal.util.Predicates$NotPredicate.apply(Predicates.java:122)
at android.test.suitebuilder.TestSuiteBuilder.satisfiesAllPredicates(TestSuiteBuilder.java:254)
at android.test.suitebuilder.TestSuiteBuilder.build(TestSuiteBuilder.java:190)
at android.test.InstrumentationTestRunner.onCreate(InstrumentationTestRunner.java:373)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4218)
at android.app.ActivityThread.access$3000(ActivityThread.java:125)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2071)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
现在我完全迷失在这里。怎么会这么复杂?我选择了正确的方法吗?我只想在测试方法中启动一个对话框。也许框架搞乱了,因为要测试的活动不在目标项目中?
这里的任何帮助将不胜感激。我已经没时间了,如果找不到合适的方法,我必须使用我的库创建第二个项目,在那里移动模拟活动并从测试项目进行测试。这是很多代码,因为我必须在(现在不是通用的)模拟活动中包含一个方法来调用我想要测试的每个库方法。
答案 0 :(得分:5)
使用androidX库,您可以使用ActivityScenario
。
只需将androidTestImplementation("androidx.test:core:1.2.0")
导入到您的app.gradle文件中
然后,在您的检测测试中,导入ActivityScenario
并使用以下命令启动活动:
import androidx.test.core.app.ActivityScenario
@Test
fun testActivity() {
ActivityScenario.launch(MainActivity::class.java).onActivity { activity ->
// do something with your activity instance
}
}
答案 1 :(得分:4)
解决!这是我做的:
要解决我上面发布的异常,只需用以下代码替换测试用例构造函数:
public LibraryTest() {
super(MockActivity.class);
}
现在可行,我可以成功启动对话框。但在我的简短研究中,我偶然发现Robotium。这个图书馆真是太棒了。我一开始并不需要它,但我发现以自动方式测试GUI非常有用。现在,我在每个setUp
调用中重新创建了一个全新的活动。
答案 2 :(得分:0)
ActivityScenario 提供 API 来启动和驱动 Activity 的生命周期状态以进行测试。它适用于任意活动,并在不同版本的 Android 框架中始终如一地工作。
val scenario = launchActivity<MyActivity>()
scenario.onActivity { activity ->
// do some stuff with the Activity
}
带有自定义 Intent
val intent = Intent(ApplicationProvider.getApplicationContext(), MyActivity::class.java)
.putExtra("title", "Testing rules!")
val scenario = launchActivity<MyActivity>(intent)
scenario.onActivity { activity ->
// do some stuff with the Activity
}
ActivityScenarioRule 在测试开始前启动给定的活动,并在测试后关闭。
您可以通过 getScenario()
方法访问场景界面。您可以在测试中手动完成您的活动,它不会导致任何问题,并且在这种情况下,此规则在测试后没有任何作用。