草庐IT

android - 如何为每个单元测试获取我的应用程序类的新实例?

coder 2023-11-20 原文

我有一个 Android 应用程序,它具有继承自 ApplicationMyApplication 类。

我创建了几个使用 @RunWith(AndroidJUnit4.class) 运行的单元测试。如果我分别运行每个测试,它们都会通过。如果我一起运行它们 - 第一个通过,然后(一些)其他人失败。

问题是似乎只创建了 MyApplication 的一个实例,然后它被保留并用于所有导致失败的测试,因为 MyApplication 中有一个状态 必须只初始化一次。

有没有办法运行单元测试(androidTest)以便为每个测试重新启动应用程序?我不在乎它是否会很慢(例如,每次都必须重新安装应用程序)我只希望测试能够独立运行。

单元测试的实际代码看起来像(按照@Zinc 的要求):

@RunWith(AndroidJUnit4.class)
public class AutoLogin_ActMainTest {
    @Rule
    public ActivityTestRule<ActMain> mActivityRule = new ActivityTestRule<ActMain>(
            ActMain.class) {


        @Override
        protected void beforeActivityLaunched() {
            super.beforeActivityLaunched();

            MyTestApp app = (MyTestApp) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext();
            DependencyInjector.reset();
            app.reset();


            FakeUnitDaggerModule fudm = new FakeUnitDaggerModule();

            Session session = new SessionImpl(new TimeProviderImpl());
            fudm.setResMain(new ResMainTest(session));

            FakeAppPrefs appPrefs = new FakeAppPrefs();
            FakeLoginPrefs loginPrefs = new FakeLoginPrefs();
            CurrentUserHolder currentUserHolder = new CurrentUserHolder();

            FakeComponent inj = DaggerFakeComponent.builder().
                    fakeMyAppDaggerModule(new FakeMyAppDaggerModule(app, appPrefs, loginPrefs, currentUserHolder)).
                    appInfoDaggerModule(new AppInfoDaggerModule("1")).
                    fakeSessionDaggerModule(new FakeSessionDaggerModule(session)).
                    fakeExchangeDaggerModule(new FakeExchangeDaggerModule("https://test.com")).
                    fakeUnitDaggerModule(fudm).
                    build();

            DependencyInjector.init(inj);
            DependencyInjector.getInstance().inject(app);


            app.onStart();
        }
    };


    @Test
    public void testAutoLogin() {
        ElapsedTimeIdlingResource idlingResource = new ElapsedTimeIdlingResource(500);
        Espresso.registerIdlingResources(idlingResource);
        idlingResource.startWaiting();

        onView(ViewMatchers.withId(R.id.tv_logged_in_as)).check(matches(isDisplayed()));
        Espresso.unregisterIdlingResources(idlingResource);
    }
}

最佳答案

The problem is that it seems that only one instance of the MyApplication is created and then it is preserved and used for all test which causes the fails because there is a state in the MyApplication which MUST be initialized only once.

恕我直言,这是应用程序中的错误,应该修复。 Application 不适合用于许多真正的业务逻辑(尽管它可以用于初始化您的崩溃报告程序库、StrictMode 等)。其他一切都应该可以单独测试,可以直接测试,也可以通过模拟、依赖注入(inject)等方式进行测试。

话虽这么说,但有时问题不在于您控制的代码,而在于来自库或框架的代码。

Is there a way to run the unit tests (androidTest) so application is restarted for each test?

现在,是的,虽然当时没有人问这个问题。 Android Test Orchestrator (ATO) 在隔离每个测试方面做得更好,但代价是测试执行速度。

关于android - 如何为每个单元测试获取我的应用程序类的新实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39993442/

有关android - 如何为每个单元测试获取我的应用程序类的新实例?的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  5. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  6. ruby - 如何为 emacs 安装 ruby​​-mode - 2

    我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby​​提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs

  7. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  8. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  9. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  10. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

随机推荐