首页 文章

使用SugarORM和Robolectric进行测试

提问于
浏览
3

我试图为我的android项目设置测试环境 . 基本的Robolectric设置完成 . 我用了这个好tutorial . 如果我在Manifest.xml中注释掉SugarORM,那么所有测试都可以 . 但如果我想与SugarORM一起使用,我总是会遇到这个错误:

显示java.lang.NullPointerException在dalvik.system.DexFile $ DFEnum.hasMoreElements(DexFile.java:239)在com.orm.SugarDb.getDomainClasses(SugarDb.java:37)在com.orm.SugarDb.createDatabase(SugarDb.java :104)在com.orm.SugarDb.onCreate(SugarDb.java:100)在android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:252)在android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java: 164)在com.orm.Database.getDB(Database.java:18)在com.orm.SugarApp.onTerminate(SugarApp.java:16)在org.robolectric.internal.ParallelUniverse.tearDownApplication(ParallelUniverse.java:133)在org.robolectric.RobolectricTestRunner $ 2.evaluate(RobolectricTestRunner.java:246)在org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)在org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)在或者是.unit4ClassRunner.run . org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71)在org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)在org.junit.runners.ParentRunner.access $ 000(ParentRunner.java: 58)维持在org.robolectric.RobolectricTestRunner $ 1.evaluate(RobolectricTestRunner.java:158)在org.junit.runners.ParentRunner.run org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:268)(ParentRunner.java :363)atg.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

每个人都有同样的问题吗?

Edit

也许是这样,因为Robolectric在测试后关机并且还没有完成 . 我的TestClass

@RunWith(RobolectricTestRunner.class)
@Config(manifest="./src/main/AndroidManifest.xml",emulateSdk=18)
public class MyActivityTest{

    private ActivityController<OnLogActivity> controller = Robolectric.buildActivity(OnLogActivity.class).create().setup();

    @Test
    public void clickingLogin_shouldStartLoginActivity() {
        OnLogActivity activity = controller.get();
        assertTrue(activity.findViewById(R.id.login) instanceof Button);

    }

}

编辑2.0:

Robolectric可以找到 android:name=com.orm.SugarApp 你需要使用相同的com.orm包创建一个测试文件夹,并添加一个名为TestSugarApp的测试类 . 之后你可以测试所有的东西 .

package com.orm;

...

@RunWith(RobolectricTestRunner.class)
@Config(manifest="./src/main/AndroidManifest.xml",emulateSdk=18)
public class TestSugarApp extends Application
        implements TestLifecycleApplication {

    private ActivityController<OnLogActivity> controller;


    @Test
    public void startEverTestSugarAppAsFirst() {

    }

    @Override
    public void beforeTest(Method method) {
        Log.v("test", "beforeTest");
    }

    @Override
    public void prepareTest(Object test) {
        Log.v("test", "prepareTest");
    }

    @Override
    public void afterTest(Method method) {
        Log.v("test", "afterTest");
    }
}

2 回答

  • 1

    好的,接下来 . 将下一个类添加到测试代码中:

    public class TestSugarApp
        extends SugarApp
    {
        @Override
        public void onCreate() {}
    
        @Override
        public void onTerminate() {}
    }
    

    名为Test的类将由Robolectric加载和使用,您可以覆盖一些与测试无关的内容 . 我试图阻止在 onCreateonTerminatehttps://github.com/satyan/sugar/blob/master/library/src/com/orm/SugarApp.java)中执行 SugarApp 的代码 .

  • 5

    @Eugen Martynov的答案完美无缺(非常感谢!) . 但是,当你自己扩展android.app.Application(它反过来扩展SugarApp),那么你也将排除自己的代码 .

    我用这个代码解决了这个问题:

    The Application class in the test code (as opposed to Eugen's answer):

    public class TestApp extends App {
        /** Prevents onCreate() and onTerminate() to call their super (in which {@link com.orm.SugarApp} is initialized) */
        @Override
        protected boolean callSuper() {
            return false;
        }
    }
    

    My own Application class (extending SugarApp):

    public class App extends com.orm.SugarApp {
        private static Context context;
    
        public static Context getContext() {
            return context;
        }
    
        @Override
        public void onCreate() {
            if (callSuper()) {
                super.onCreate();
            }
    
            // My own code is always executed, also during unittests
            context = getApplicationContext();
        }
    
        @Override
        public void onTerminate() {
            if (callSuper()) {
                super.onTerminate();
            }
        }
    
        protected boolean callSuper() {
            return true; // Super is executed by default
        }
    }
    

    我同意它看起来不是很漂亮(任何建议让它变得更好?),但它对我来说非常合适!

    PS . 我在我的清单中声明了我的应用程序类:

    <application
        android:name=".App"
    

相关问题