gpt4 book ai didi

android - 为 Presenter 的私有(private)方法编写单元测试

转载 作者:行者123 更新时间:2023-11-28 20:26:07 24 4
gpt4 key购买 nike

我正在为 MVP 项目的演示者编写单元测试。

class SplashPresenter {
override fun onAttach() {
if (dataManager.getAppLaunchFirstTime()) {
onAppOpenFirstTime()
} else {
// Other logic...
}
}

@VisibleForTesting
fun onAppOpenFirstTime() {
dataManager.setAppLaunchFirstTime(false)
splashView.openLoginScreen()

// May be I will add more functionalities in the future...
}
}

这里我们有2种方法来编写单元测试。

第一种方法

直接验证会发生什么:openLoginScreen() & setAppLaunchFirstTime(false)。不关心他们将如何被调用。

@Test
fun onAttachTest_appLaunchFirstTime() {
Mockito.`when`(dataManager.getAppLaunchFirstTime()).thenReturn(true)

splashPresenter.onAttach()

verify(dataManager).setAppLaunchFirstTime(false)
verify(splashView).openLoginScreen()
}

第二种方法

我们使用 spy() 来验证私有(private)内部方法 onAppOpenFirstTime() 是否会被调用。然后为 onAppOpenFirstTime() 编写另一个单独的测试

@Test
fun onAttachTest_appLaunchFirstTime() {
`when`(dataManager.getAppLaunchFirstTime()).thenReturn(true)
val spyPresenter = Mockito.spy(splashPresenter)

spyPresenter.onAttach()

verify(spyPresenter).onAppOpenFirstTime()
}

@Test
fun onAppOpenFirstTimeTest() {
splashPresenter.onAppOpenFirstTime()

verify(dataManager).setAppLaunchFirstTime(false)
verify(splashView).openLoginScreen()
}

那么哪种方法更好呢?在将来扩展功能时,哪种方法将使项目更易于测试

我们需要为私有(private)内部方法编写单元测试吗?

最佳答案

(您已经问过哪种方法会使项目更易于测试,但可测试性是被测系统的一个属性。然而,本例中测试套件的显着属性是测试代码维护的努力。)

在您的特定示例中,第二种方法使您的测试不必要地依赖于可能会更改的实现细节:您可能重命名onAppOpenFirstTime,将其拆分为更多辅助函数,甚至删除它并将其内联到 onAttach 中。在所有这些变更场景中,第二种方法将导致额外的维护工作以保持测试套件正常工作。

不过,我强调这里不需要依赖onAppOpenFirstTime。这是因为采用第二种方法没有任何好处:第一种方法似乎能够找到与第二种方法相同的错误,第一种方法中的测试与第二种方法一样容易设置(甚至更容易)等等上。


如果你只想知道如何解决所描述的特定问题,你可以停止阅读这里。然而,在其他情况下,情况可能有所不同。我在下面添加评论,因为我不是经常说的口头禅“不要测试私有(private)方法”的提倡者。

尝试使单元测试套件完全独立于实现细节可能会导致测试套件效率低下 - 也就是说,测试套件不适合查找所有可能发现的错误。而且,发现错误是测试的主要目标之一(请参阅 Myers、Badgett、Sandler:软件测试的艺术,或 Beizer:软件测试技术等)。

错误最终出现在实现中。不同的实现会有不同的bug。因此,尝试拥有一个与实现无关的测试套件可能无法找到错误。

考虑实现 Fibonacci 函数的不同方法:作为迭代/递归函数、封闭形式表达式 (Moivre/Binet)、查找表:每种实现都会带来不同的潜在错误。单元测试是test pyramid底部的测试方法,并且所有更高级别的测试(集成或系统测试)不太适合在实现细节中查找错误。

因此,最好的方法是拥有尽可能多的独立于实现的有用单元测试。此外,您可能需要额外的单元测试,旨在发现所选实现中的潜在错误。最后,您的测试套件可能是两者的混合体:独立于实现的测试和特定于实现的测试。

依赖于实现的测试将更加维护密集,因此对于每一个你都应该有一个理由,例如检测特定于实现的潜在错误。特定于实现的测试本身并不是坏事,但不要在不必要的情况下使用它们。而且,实现方面越不稳定,您就越应该避免让您的测试依赖于它。

参见 Meszaros Principles of Test Automation: Ensure Commensurate Effort

关于android - 为 Presenter 的私有(private)方法编写单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56504337/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com