当前位置: 首页 > news >正文

网站建设首选公司朝阳网站seo

网站建设首选公司,朝阳网站seo,好看的网站模板,陕西渭南富平建设局网站翻译自 https://medium.com/mindorks/how-to-unit-test-private-methods-in-java-and-kotlin-d3cae49dccd ❓如何单元测试 Kotlin/Java 中的 private 方法❓ 首先,开发者应该测试代码里的 private 私有方法吗? 直接信任这些私有方法,测试到…

在这里插入图片描述

翻译自 https://medium.com/mindorks/how-to-unit-test-private-methods-in-java-and-kotlin-d3cae49dccd

❓如何单元测试 Kotlin/Java 中的 private 方法❓

首先,开发者应该测试代码里的 private 私有方法吗?

直接信任这些私有方法,测试到调用它们的公开方法感觉就够了吧。

对于这个争论,每个开发者都会有自己的观点。

但回到开头的问题本身,到底有没有一种合适的途径来实现私有方法的单元测试

截止到目前,在面对单元测试私有方法的问题时,一般有如下几种选择:

  1. 不去测试私有方法 😜*(选择信任,直接躺平)*

  2. 将目标方法临时改成 public 公开访问权限 😒(可我不愿意这样做,这不符合代码规范。作为一名开发者,我要遵循最佳实践

  3. 使用嵌套的测试类 😒*(将测试代码和生产代码混到一起不太好吧,我再强调一遍:我是很优秀的开发者,要遵循最佳实践)*

  4. 使用 Java 反射机制 😃*(听起来还行,可以试试这个方案)*

大家都知道通过 Java 反射机制可以访问到其他类中的私有属性和方法,而且写起来也不麻烦,在单元测试里采用该机制应该也很容易上手。

注意

只有将代码作为独立的 Java 程序运行时,这个方案才适用,就像单元测试、常规的 Java 应用程序。但如果在 Java Applet 上执行反射,则需要对 SecurityManager 做些干预。由于这不是高频场景,本文不对其作额外阐述。

Java 8 中添加了对反射方法参数的支持,使得开发者可以在运行时获得参数名称。

访问私有属性

Class 类提供的 getField(String name)getFields() 只能返回公开访问权限的属性,访问私有权限的属性则需要调用 getDeclaredField(String name)getDeclaredFields()

下面是一个简单的代码示例:一个拥有私有属性的类以及如何通过 Java 反射来访问这个属性。

public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {this.privateString = privateString;}
}PrivateObject privateObject = new PrivateObject("The Private Value");
Field privateStringField = PrivateObject.class.getDeclaredField("privateString");privateStringField.setAccessible(true);String fieldValue = (String) privateStringField.get(privateObject);System.out.println("fieldValue = " + fieldValue);

上述代码将打印出如下结果:内容来自于 PrivateObject 实例的私有属性 privateString 的值。

fieldValue = The Private Value

需要留意的是,getDeclaredField("privateString") 能返回私有属性没错,但其范围仅限 class 本身,不包含其父类中定义的属性。

还有一点是需要调用 Field.setAcessible(true),目的在于关闭反射里该 Field 的访问检查。

这样的话,如果访问的属性是私有的、受保护的或者包可见的,即使调用者不满足访问条件,仍然可以在反射里获取到该属性。当然,非反射的正常代码里依然无法获取到该属性,不受影响。

访问私有方法

和访问私有属性一样,访问私有方法需要调用 Class 类提供的 getDeclaredMethod(String name, Class[] parameterTypes)Class.getDeclaredMethods()

同样的,我们展示一段代码示例:定义了私有方法的类以及通过反射访问它。

public class PrivateObject {private String privateString = null;public PrivateObject(String privateString) {this.privateString = privateString;}private String getPrivateString(){return this.privateString;}
}PrivateObject privateObject = new PrivateObject("The Private Value");
Method privateStringMethod = PrivateObject.class.getDeclaredMethod("getPrivateString", null);privateStringMethod.setAccessible(true);String returnValue = (String)
privateStringMethod.invoke(privateObject, null);System.out.println("returnValue = " + returnValue);

打印出的结果来自于 PrivateObject 实例中私有方法 getPrivateString() 的调用结果。

returnValue = The Private Value

注意点和访问私有属性一样:

  1. getDeclaredMethod() 存在 class 本身的范围限制,不能获取到父类中定义的任何方法
  2. 需要调用 Method.setAcessible(true) 来关闭反射中的 Method 的访问权限检查,确保即便不满足访问条件,亦能在反射中成功访问

了解完通过反射来访问私有属性、方法的知识之后,让我们用在 unit test 中来测试本来难以覆盖到的私有方法。

LoginPresenter.kt

比如,我们的代码库中存在如下类 LoginPresenter,并且咱们想要去单元测试其私有方法 saveAccount()

class LoginPresenter @Inject constructor(private val view: LoginView,private val strategy: CancelStrategy,private val navigator: AuthenticationNavigator,private val tokenRepository: TokenRepository,private val localRepository: LocalRepository,private val settingsInteractor: GetSettingsInteractor,private val analyticsManager: AnalyticsManager,private val saveCurrentServer: SaveCurrentServerInteractor,private val saveAccountInteractor: SaveAccountInteractor,private val factory: RocketChatClientFactory,val serverInteractor: GetConnectingServerInteractor
) {private var currentServer = serverInteractor.get() ?: defaultTestServerprivate val token = tokenRepository.get(currentServer)private lateinit var client: RocketChatClientprivate lateinit var settings: PublicSettingsfun setupView() {setupConnectionInfo(currentServer)setupForgotPasswordView()}private fun setupConnectionInfo(serverUrl: String) {currentServer = serverUrlclient = factory.get(currentServer)settings = settingsInteractor.get(currentServer)}private fun setupForgotPasswordView() {if (settings.isPasswordResetEnabled()) {view.showForgotPasswordView()}}fun authenticateWithUserAndPassword(usernameOrEmail: String, password: String) {launchUI(strategy) {view.showLoading()try {val token = retryIO("login") {when {settings.isLdapAuthenticationEnabled() ->client.loginWithLdap(usernameOrEmail, password)usernameOrEmail.isEmail() ->client.loginWithEmail(usernameOrEmail, password)else ->client.login(usernameOrEmail, password)}}val myself = retryIO("me()") { client.me() }myself.username?.let { username ->val user = User(id = myself.id,roles = myself.roles,status = myself.status,name = myself.name,emails = myself.emails?.map { Email(it.address ?: "", it.verified) },username = username,utcOffset = myself.utcOffset)localRepository.saveCurrentUser(currentServer, user)saveCurrentServer.save(currentServer)localRepository.save(LocalRepository.CURRENT_USERNAME_KEY, username)saveAccount(username)saveToken(token)analyticsManager.logLogin(AuthenticationEvent.AuthenticationWithUserAndPassword,true)view.saveSmartLockCredentials(usernameOrEmail, password)navigator.toChatList()}} catch (exception: RocketChatException) {when (exception) {is RocketChatTwoFactorException -> {navigator.toTwoFA(usernameOrEmail, password)}else -> {analyticsManager.logLogin(AuthenticationEvent.AuthenticationWithUserAndPassword,false)exception.message?.let {view.showMessage(it)}.ifNull {view.showGenericErrorMessage()}}}} finally {view.hideLoading()}}}fun forgotPassword() = navigator.toForgotPassword()private fun saveAccount(username: String) {val icon = settings.favicon()?.let {currentServer.serverLogoUrl(it)}val logo = settings.wideTile()?.let {currentServer.serverLogoUrl(it)}val thumb = currentServer.avatarUrl(username, token?.userId, token?.authToken)val account = Account(settings.siteName() ?: currentServer,currentServer,icon,logo,username,thumb)saveAccountInteractor.save(account)}private fun saveToken(token: Token) = tokenRepository.save(currentServer, token)
}

LoginPresenterTest.kt

单元测试的整体如下:

class LoginPresenterTest {private val view = mock(LoginView::class.java)private val strategy = mock(CancelStrategy::class.java)private val navigator = mock(AuthenticationNavigator::class.java)private val tokenRepository = mock(TokenRepository::class.java)private val localRepository = mock(LocalRepository::class.java)private val settingsInteractor = mock(GetSettingsInteractor::class.java)private val analyticsManager = mock(AnalyticsManager::class.java)private val saveCurrentServer = mock(SaveCurrentServerInteractor::class.java)private val saveAccountInteractor = mock(SaveAccountInteractor::class.java)private val factory = mock(RocketChatClientFactory::class.java)private val serverInteractor = mock(GetConnectingServerInteractor::class.java)private val token = mock(Token::class.java)const val currentServer: String = "https://open.rocket.chat"const val USERNAME: String = "user121"const val PASSWORD: String = "123456"lateinit var loginPresenter: LoginPresenterprivate val account = Account(currentServer, currentServer, null,null, USERNAME, UPDATED_AVATAR)@Beforefun setUp() {MockitoAnnotations.initMocks(this)`when`(strategy.isTest).thenReturn(true)`when`(serverInteractor.get()).thenReturn(currentServer)loginPresenter = LoginPresenter(view, strategy, navigator, tokenRepository, localRepository, settingsInteractor,analyticsManager, saveCurrentServer, saveAccountInteractor, factory, serverInteractor)}@Testfun `check account is saved`() {...}
}

通过反射机制,私有方法 saveAccount() 的单测则可以很方便地进行。

class LoginPresenterTest {...@Testfun `check account is saved`() {loginPresenter.setupView()val method = loginPresenter.javaClass.getDeclaredMethod("saveAccount", String::class.java)method.isAccessible = trueval parameters = arrayOfNulls<Any>(1)parameters[0] = USERNAMEmethod.invoke(loginPresenter, *parameters)verify(saveAccountInteractor).save(account)}
}

本文浅显易懂,希望能向你展示反射的魔力,帮助开发者在单元测试中优雅、便捷地 cover 到私有方法!

最后,感谢你的阅读。

http://www.khdw.cn/news/8970.html

相关文章:

  • 做网站卖产品成品网站货源1688在线
  • 重庆城乡建设委员会的网站杭州seo平台
  • 企业单位网站建设内容需要什么推广app的方法和策略
  • 做平台好还是自己建网站seo咨询河北
  • 系统开发需求文档seo网页优化工具
  • 哪个网站有上门做指甲公司网站设计图
  • 网站设计怎么保持风格一致北京网站推广营销服务电话
  • 专做五金正品的网站营销网站建设选择
  • 佛山做网站公司排名手机端关键词排名优化软件
  • 广州市公共资源交易中心优化深圳seo
  • 用dw做网站找关键词的方法与技巧
  • 福清网站建设十大搜索引擎网站
  • 中企动力做的网站升级收费怎么推广自己的微信
  • 海南论坛论坛网站建设最吸引人的引流话术
  • 东莞网站建设分享seo推广任务接单平台
  • 上海疫情防控最新政策北京百度seo排名公司
  • 柳城网站制作天津网站建设技术外包
  • iis下建立asp网站seo优化网站源码
  • 网站建设经济可行性b2c有哪些电商平台
  • 怎么自己创建一个网站芜湖网络营销公司
  • 免费做网站txt外链厦门关键词排名优化
  • 安卓手机应用开发福州网站优化公司
  • 中国最好的网站制作公司百度一下 官方网
  • 县 两学一做网站网络推广服务合同
  • h5 响应式网站国外免费加客源软件
  • 做交易网站什么开发语言网络广告营销的案例
  • 网站建设合同补充内容营销策划公司是干什么的
  • 深圳公司手机网站制作抖音优化排名
  • 学校网站类型免费发布推广的平台
  • 美国客户打不开我们的网站百度引流免费推广怎么做