findFragmentByTag的单元测试条件

时间:2018-02-15 17:21:02

标签: android unit-testing junit kotlin robolectric

Android Studio 3.2 Canary 2
Build #AI-173.4591728, built on February 8, 2018
JRE: 1.8.0_152-release-1024-b01 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Linux 4.14.18-300.fc27.x86_64

我有以下活动,我想单元测试片段已经附加的情况,并且应该返回非null。并且应该落入其他条件:

这是我的活动:

public class BillingActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.billing_container);

        if(getSupportFragmentManager().findFragmentByTag(BillingView.TAG) == null) {
            final FragmentTransaction fragmentTransaction =
                    getSupportFragmentManager().beginTransaction();

            fragmentTransaction.add(
                    R.id.billing_view_container,
                    BillingView.newInstance(),
                    BillingView.TAG);

            fragmentTransaction.commit();
        }
        else {
            Timber.d("Fragment already attached");
        }
    }
}

测试类是这样的:我可以编写测试来附加一个片段,但我想在片段已经附加时测试条件并且应该返回非null。

class BillingActivityTest: BaseRobolectricTestRunner() {
    private lateinit var billingActivity: BillingActivity

    @Before
    fun setup() {
        billingActivity = Robolectric.buildActivity(BillingActivity::class.java)
                .create()
                .start()
                .get()
    }

    @Test
    fun testBillingActivityIsNotNullValue() {
        assertThat(billingActivity, `is`(notNullValue()))
    }

    @Test
    fun testBillingFragmentHasStarted() {
        val actualFragment = billingActivity
                .supportFragmentManager
                .findFragmentByTag(BillingView.TAG)

        assertThat(actualFragment.tag, `is`(BillingView.TAG))
    }

    @Test
    fun testBillingFragmentAlreadyAttached() {
        /* how to test */
    }
}

感谢您的任何建议,

2 个答案:

答案 0 :(得分:8)

方法you've chosen(使用recreate())只要复制您请求的行为就会有效。我相信这是最简单的方法。

尽管如此,我不能认为它是一个纯粹的单元测试,因为实际上你是在作弊,因为很明显你对这个活动的 class MainActivity : AppCompatActivity() { internal var fragmentManagerRetriever = FragmentManagerRetriever() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val fragmentManager = fragmentManagerRetriever.getFragmentManager(this) if (fragmentManager.findFragmentByTag("TAG") == null) { val fragmentTransaction = fragmentManager.beginTransaction() fragmentTransaction.add(SomeFragment(), "TAG") fragmentTransaction.commit() } } } 动作不感兴趣(这可能带来副作用)

如果你想进行纯单元测试,那么就是这样做的方法。宣布活动如此:

FragmentManagerRetriever

class FragmentManagerRetriever { public FragmentManager getFragmentManager(FragmentActivity activity) { return activity.getSupportFragmentManager(); } } 就像这样简单:


    @Test
    fun nullCase() {
        val activityController = Robolectric.buildActivity(MainActivity::class.java)
        val activity = activityController.get()

        val fragmentManagerRetriever = mock(FragmentManagerRetriever::class.java)
        val fragmentManager = mock(FragmentManager::class.java)
        val fragmentTransaction = mock(FragmentTransaction::class.java)
        activity.fragmentManagerRetriever = fragmentManagerRetriever

        `when`(fragmentManagerRetriever.getFragmentManager(activity)).thenReturn(fragmentManager)
        `when`(fragmentManager.findFragmentByTag("TAG")).thenReturn(null)
        `when`(fragmentManager.beginTransaction()).thenReturn(fragmentTransaction)

        activityController.create()

        val inOrder = Mockito.inOrder(fragmentTransaction)
        inOrder.verify(fragmentTransaction).add(ArgumentMatchers.any(SomeFragment::class.java), ArgumentMatchers.eq("TAG"))
        inOrder.verify(fragmentTransaction).commit()
    }

然后你有一个接缝来执行纯单元测试:


    @Test
    fun nonNullCase() {
        val activityController = Robolectric.buildActivity(MainActivity::class.java)
        val activity = activityController.get()

        val fragmentManagerRetriever = mock(FragmentManagerRetriever::class.java)
        val fragmentManager = mock(FragmentManager::class.java)
        val fragmentTransaction = mock(FragmentTransaction::class.java)
        activity.fragmentManagerRetriever = fragmentManagerRetriever

        `when`(fragmentManagerRetriever.getFragmentManager(activity)).thenReturn(fragmentManager)
        `when`(fragmentManager.findFragmentByTag("TAG")).thenReturn(mock(Fragment::class.java))

        activityController.create()

        verifyZeroInteractions(fragmentTransaction)
    }

测试非空案例:

{{1}}

答案 1 :(得分:3)

我通过调用activity.recreate()

设法做到这一点
@Test
fun testBillingFragmentAlreadyAttached() {
     billingActivity.recreate()

     val actualFragment = billingActivity
            .supportFragmentManager
            .findFragmentByTag(BillingView.TAG)

     assertThat(actualFragment.tag, `is`(BillingView.TAG))
}

但如果有人有更好的方法。听听另一种解决方案会很好。