【问题标题】:Restarting application on android test在android测试上重新启动应用程序
【发布时间】:2015-12-18 18:59:14
【问题描述】:

我正在创建一个库,它将根据用户默认设置处理信息并将其保存在 SharedPreferences 中,开发人员可以在初始化我的库之前在其应用程序上对其进行修改。

每个应用实例只应初始化一次 SDK,否则会触发 RuntimeError。所以在应用程序端的 Application 类应该是这样的:

public class SampleApplication extends Application {
    @Override
    public void onCreate() {
       super.onCreate();

       //Here I can do something that will change the default configs

       //Here I initialize the SDK singleton method
       Sdk.initialize();
    }
}

sdk 抽象实现:

public class Sdk {

    private static SampleApplication sInstance;

    private void Sdk(){
    }

    public static SampleApplication getInstance() throws RuntimeException {
        if (sInstance == null) {
            throw new RuntimeException();
        }
        return sInstance;
    }

    public static void initialize() {
        if (sInstance == null) {
            sInstance = new Sdk();
            //save some information according to what is on the default configurations
        } else {
            throw new RuntimeException("Method was already initialized");
        }
    }
}

当我想测试几个场景来调用这个方法(每个应用程序实例只能调用一次)时,问题就来了。

所以我创建了一个扩展 ApplicationTest 的 Android 测试

应用测试:

  public class ApplicationTest extends ApplicationTestCase<SampleApplication> {
        public ApplicationTest() {
            super(SampleApplication.class);
        }
    }

Android 测试示例:

public class SampleTest extends ApplicationTest {

    @Override
    protected void setUp() throws Exception {
// Here I restart the user preferences although I need to restart the application
//        terminateApplication();
//        createApplication();
        super.setUp();
    }

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();
    }

    public void testDefaultSettings() {
        // Here is where I want to restart application input
        // some values on the user preferences settings in order 
        // to test the output on sharedpreferences by the initialized method  
    }
}

我尝试终止并再次创建应用程序,但没有成功。 我的问题是可以重新启动Android测试的应用程序吗? 我在这里做错了吗?

【问题讨论】:

    标签: android unit-testing android-testing


    【解决方案1】:

    我相信,您真正遇到的问题是 InstrumentationTestRunner 的问题:How to prevent ActivityUnitTestCase from calling Application.onCreate?(显然,没有明显的解决方法)

    即无论如何,TestRunner 都会在初始化期间调用onCreate(),所以一旦你调用createApplication(),你的Sdk 就已经初始化了。

    关于问题本身 - 我相信,唯一的选择是重新考虑 Sdk 类的架构(或添加一些“重置”功能等)

    public class TestApplication extends Application {
    
        @Override
        public void onCreate() {
            super.onCreate();
            // Sdk.terminate(); - If you specify TestApplication as an 
            //                    application class in AndroidManifest, 
            //                    you'll have to uncomment this(due to issue with test runner)
            Sdk.initialize();
        }
    
        @Override
        public void onTerminate() {
            super.onTerminate();
            Sdk.terminate();
        }
    }
    

    Sdk

    public class Sdk {
    
        private static Sdk sInstance;
        private void Sdk(){
        }
    
        public static Sdk getInstance() throws RuntimeException {
            if (sInstance == null) {
                throw new RuntimeException();
            }
            return sInstance;
        }
    
        public static void terminate() {
            sInstance = null;
        }
    
        public static void initialize() {
            if (sInstance == null) {
                sInstance = new Sdk();
                //save some information according to what is on the default configurations
            } else {
                throw new RuntimeException("Method was already initialized");
            }
        }
    }
    

    测试:

    public class MyApplicationTest extends ApplicationTestCase<TestApplication> {
    
        public MyApplicationTest() {
            super(TestApplication.class);
        }
    
        public void testMultiplicationTests() {
            createApplication();
    
            int answer = 42;
            assertEquals(42, answer);
    
            terminateApplication();
        }
    
    
        public void testDefaultSettings() {
            createApplication();
    
            assertNotNull(Sdk.getInstance());
    
            terminateApplication();
        }
    }
    

    注意!如果你为 androidTest 应用特殊的 AndroidManifest,你可以让它不那么痛苦。然后,当 TestRunner 在测试开始之前自行调用 onCreate() 时,您将不会遇到问题。

    希望对你有帮助

    【讨论】:

    • 您好,感谢您对测试运行器如何真正工作的解释。我只是对您的建议有一个疑问,“每个类 1 个测试”您的意思是每次安装运行一个测试类吗?
    • @iGoDa,我的意思是一旦你有多个类,每个类都扩展 ApplicationTestCase,每个类都会创建应用程序的新实例 => 它们之间不会有重叠。但同样,这有点难看,并且限制了每个 ApplocationTesCase 类只能有一个测试。
    • androidTest 是否接受每个 androidTest 包的多个 applicationTestCases?毕竟 androidTest 是一个应用程序对吗?我是否需要更改任何配置才能正常工作?
    • @iGoDa 好的,我检查过了 - 你是对的,这将是相同的测试应用程序实例。因此,您唯一的选择是使用重置方法(或任何其他手动清理)用于测试目的。我会修复答案
    • @iGoDa 我很高兴。我添加了几个cmets。这是非常错误的,它是如此棘手。例如,为了避免 onCreate() 调用 - 您需要从当前的 Manifest "android:name" 属性中删除,或者每次在 OnCreate() 中调用 SDK 的终止,或者找到一种方法来应用自定义 AndroidManifest 进行仪器测试(这非常棘手 - 我现在花了 2 个小时试图找到一个合适的解决方案并且绝对没有记录)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-02
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 1970-01-01
    相关资源
    最近更新 更多