【问题标题】:How to unit test interaction between FragmentDialog and Activity which implements interface如何对实现接口的 FragmentDialog 和 Activity 之间的交互进行单元测试
【发布时间】:2015-08-20 10:58:12
【问题描述】:

我有 MainActivity 显示 FragmentDialog (EditIntervalFragment) 以捕获用户的输入。 Activity 实现了EditIntervalListener 接口。在onAtach 方法片段中将活动转换为EditIntervalListener。 我想测试我的EditIntervalFragment 是否正确调用具有正确参数的EditIntervalListener 方法。

我最初的意图是使用 Roblectric 和 Mockito。下面的代码几乎可以工作。

@Test
public void shouldCallInterfaceAfterModify() {
    MainActivity hostActivity = Robolectric.setupActivity(MainActivity.class);
    EditIntervalFragment editIntervalFragment = EditIntervalFragment.getInstance(0, TEST_NAME, TEST_DURATION);
    editIntervalFragment.show(hostActivity.getSupportFragmentManager(), "test");
    AlertDialog dialog = (AlertDialog) editIntervalFragment.getDialog();
    assertNotNull(dialog);

    EditIntervalFragment.EditIntervalListener activity = Mockito.spy(hostActivity);
    dialog.findViewById(android.R.id.button1).performClick();
    verify(activity).onIntervalChanged(0,TEST_NAME,TEST_DURATION);
}

这个代码的问题是它使用了真正的MainActivity。这意味着将执行所有MainActivity 的逻辑。我想避免这种情况。我该怎么做?

更新 我找到了一种不调用真实MainActivity 的方法。我创建了另一个活动,只是为了测试。

public class ActivityTest extends FragmentActivity implements EditIntervalFragment.EditIntervalListener {

    //empty methods here
}

我的测试现在看起来像这样

@Test
public void shouldCallInterfaceAfterModify() {
    ActivityTest hostActivity = Robolectric.setupActivity(ActivityTest.class);
    ActivityTest spy = Mockito.spy(hostActivity);
    EditIntervalFragment editIntervalFragment = EditIntervalFragment.getInstance(0, TEST_NAME, TEST_DURATION);
    editIntervalFragment.show(spy.getSupportFragmentManager(), "test");
    AlertDialog dialog = (AlertDialog) editIntervalFragment.getDialog();
    assertNotNull(dialog);

    dialog.findViewById(android.R.id.button1).performClick();
    verify(spy).onIntervalChanged(0, TEST_NAME, TEST_DURATION);
}

但在测试执行后,我收到错误消息说只有spy.getSupportFragmentManager() 被调用。我 100% 确定应该调用 onIntervalChanged

寻求帮助。我怎样才能实现这样的测试?

【问题讨论】:

    标签: android mockito robolectric android-testing


    【解决方案1】:

    当您无法控制生命周期时,制作工作间谍总是很困难的。

    我们通常会提取所有不相关的功能到实用程序类并在测试中模拟它们。它还有助于设计应用程序(单一类责任规则)。

    当然,这取决于您是否对这些数据进行处理。如果它只是数据类,我将拥有Factory 来创建这个数据类并再次在测试中模拟它。所有这些都需要适当的 DI(看 Dagger)。

    您的方法没有任何问题,但它不会强迫您将应用视为相互交互的小部分。但同时它带来了更多的复杂性,以后会得到回报

    【讨论】:

    • 谢谢。我被这种onAtach - getActivity - cast to listener 方法卡住了。主要是因为我到处都能看到它(甚至AndroidStudio都会生成这样的片段)。现在,我最终为我的对话安排了一位专门的演示者。与活动完全没有联系。我喜欢它:)
    【解决方案2】:

    我最终得到了这个解决方案。创建一个实现接口并跟踪所有交互的 Activity。

    public class ActivityTest extends FragmentActivity implements EditIntervalFragment.EditIntervalListener {
    
        public int mIntervalChangedCalls = 0;
        public int mPosition;
        public String mName;
        public long mDurationMillSec;
    
        @Override
        public void onIntervalChanged(int position, String name, long durationMillSec) {
            mIntervalChangedCalls++;
            mPosition = position;
            mName = name;
            mDurationMillSec = durationMillSec;
        }
    }
    

    我的测试是这样的

    @Test
    public void shouldCallOnIntervalChanged() {
        ActivityTest hostActivity = Robolectric.setupActivity(ActivityTest.class);
        EditIntervalFragment editIntervalFragment = EditIntervalFragment.getInstance(0, TEST_NAME, TEST_DURATION);
        editIntervalFragment.show(hostActivity.getSupportFragmentManager(), "test");
        AlertDialog dialog = (AlertDialog) editIntervalFragment.getDialog();
        assertNotNull(dialog);
    
        dialog.findViewById(android.R.id.button1).performClick();
        assertThat(hostActivity.mIntervalChangedCalls).isEqualTo(1);
        assertThat(hostActivity.mPosition).isEqualTo(0);
        assertThat(hostActivity.mName).isEqualTo(TEST_NAME);
        assertThat(hostActivity.mDurationMillSec).isEqualTo(TEST_DURATION);
    }
    

    我对仅仅为了测试目的而创建一个单独的类并不完全满意。我想使用 Mockito 或 Robolectric 也可以达到同样的效果,但我不知道如何。

    所以我仍然愿意接受任何想法或建议。如果一周内没有人给出更好的解决方案,我会接受我自己的答案。

    【讨论】:

      猜你喜欢
      • 2023-03-17
      • 2016-10-23
      • 1970-01-01
      • 2011-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-12
      • 2020-06-22
      相关资源
      最近更新 更多