我目前继承了一个代码覆盖率为零的Android应用程序,我的第一个工作就是为它编写一些单元测试。所以我决定也把它作为学习Robolectric的机会。
但是我遇到了初始问题,需要运行两个简单的虚拟测试。
这是我的测试文件中的代码:
@Config(constants = BuildConfig.class)
@RunWith(RobolectricGradleTestRunner.class)
public class SplashActivityTest {
private SplashActivity activity;
// @Before => JUnit 4 annotation that specifies this method should run before each test is run
// Useful to do setup for objects that are needed in the test
@Before
public void setup() {
// Convenience method to run SplashActivity through the Activity Lifecycle methods:
// onCreate(...) => onStart() => onPostCreate(...) => onResume()
activity = Robolectric.setupActivity(SplashActivity.class);
}
// @Test => JUnit 4 annotation specifying this is a test to be run
// Checking that the UI gets setup correctly
@Test
public void dummy() {
String test = "POP!";
assertTrue("POP!",
test.equals("POP!"));
}
@Test
public void dummyTwo() {
String test = "POP!!";
assertTrue("POP!!",
test.equals("POP!!"));
}
}
问题是活动扩展了另一个名为baseactivity的类,在这个类中使用了一个自定义的Application类。
在此自定义应用程序类中,使用以下代码将Picasso创建为Singleton:
picasso = new Picasso.Builder(getApplicationContext()).downloader(new OkHttpDownloader(picassoClient)).build();
Picasso.setSingletonInstance(picasso);
当我运行测试时,我收到以下错误:
java.lang.IllegalStateException:Singleton实例已存在。 在 com.squareup.picasso.Picasso.setSingletonInstance(Picasso.java:677)
所以看起来应用程序类被创建了两次,每次测试一次,因为一次测试运行正常。所以我假设我的测试模式在这里是错误的?任何人都可以用正确的模式帮助我吗?与单元测试一样,我想测试有限的功能,所以我不确定我在做什么是正确的。
编辑:我试图设置一个“模拟”应用程序类并让Robolectric使用它,但它似乎仍然使用真正的Application类。
所以在test / java中我有以下类:
public class TestMyApplication extends MyApplication
implements TestLifecycleApplication {
@Override
public void onCreate() {
super.onCreate();
initPicasso();
}
@Override
protected void initPicasso() {
//nothing to do
}
@Override public void beforeTest(Method method) {
}
@Override public void prepareTest(Object test) {
}
@Override public void afterTest(Method method) {
}
}
正如你所看到的,它扩展了MyApplication类,它位于我的主应用程序中,我还将@Override添加到initPicasso方法以尝试阻止它被调用,但是当我运行我的测试时,我仍然得到错误Picasso Singleton第二次参加第二次测试。
因此,当我运行我的测试类时,它仍然会进入我的主应用程序中的Application类,为什么当单元测试的范围有限时,Robolectric会这样做?
我也试过这个:
@Config(constants = BuildConfig.class, application = TestMyApplication.class)
但是当我尝试这个并运行测试类时,我得到一个错误,说它找不到TestMyApplication,所以它撕裂我的头发问题为什么Robolectric不会使用我的模拟Application类。
答案 0 :(得分:4)
为了使它工作,我必须创建以下类,它扩展了RobolectricGradleTestRunner并强制它使用TestMyApplication类。
public class TestRunner extends RobolectricGradleTestRunner {
public TestRunner(final Class<?> testClass) throws InitializationError {
super(testClass);
}
@Override
protected Class<? extends TestLifecycle> getTestLifecycleClass() {
return MyTestLifecycle.class;
}
public static class MyTestLifecycle extends DefaultTestLifecycle {
@Override
public Application createApplication(final Method method, final AndroidManifest appManifest, final Config appConfig) {
// run tests under our TestApplication
return new TestMyApplication();
}
}
}
然后在TestMyApplication类中,我必须覆盖initPicasso方法:
@Override protected void initPicasso(){
//do nothing
}
只有在这样做之后,Robolectric才会跳过主MyApplication.java类中的initPicasso。
答案 1 :(得分:2)
在Robolectric 3.4.2中,在测试工作中使用自定义Application类:
public class MyApplication extends Application {
protected void initPicasso() {
// do Picasso initialization
}
}
public class TestMyApplication extends MyApplication {
@Override
protected void initPicasso() {
//nothing to do
}
}
只需在测试类中添加一个Config注释:
@Config(constants = BuildConfig.class, application = TestMyApplication.class)