java - 使用对象实例化测试一段代码的良好实践
问题描述
是否有任何指导方针(或最佳实践)来整理以下内容?
我有以下方法来测试:
fun findProfileByPersonalInfo(personInfo: PersonalInfo): Profile? {
localProfileRepository.findByPersonalInfo(personalInfo)?.let {
return it
}
val searchParams = RemoteProfileSearchParameters()
//... Some mapping from personalInfo to searchParams
remoteProfileRepository.findRemoteProfile(searchParams)?.let {
val profile = profileFactory.create(remoteProfile)
return save(profile)
}
return null
}
当我开始为这个函数编写单元测试时,我意识到:
- 测试线路既简单又方便,
val profile = profileFactory.create(remoteProfile)
因为我可以模拟此调用的结果并分别测试从其他地方remoteProfile
到profile
其他地方的映射。有了这个,如果我改变映射的逻辑,我不会破坏我的测试findProfileByPersonalInfo
,这很好。 - 反之亦然,如果从映射
personalInfo
到的逻辑searchParams
属于,感觉不太对,很难维护测试findProfileByPersonalInfo
。
问题是:
- (几乎)总是将实例化逻辑从被测函数中移动以使其更具可测试性和可维护性是否可以?毫无疑问,唯一的职责是实例化对象的函数是个例外。
- 为每个属于上述情况的对象创建某种类型的工厂是不是太过分了?系统的整体设计似乎因此受到影响。
非常感谢对最佳实践或讨论的任何参考。非常感谢!
解决方案
这有点宽泛,通常您希望方法不要做太多并将可重用的代码部分移动到单独的方法中。基于您展示的有限上下文,在这种情况下,出于可测试性和可读性的原因,我肯定会将实例化移出。
您并不总是需要一个成熟的工厂,根据上下文,一个简单的构造函数
RemoteProfileSearchParameters(personInfo: PersonalInfo)
可能是最明智的。根据复杂性,这可能会被重构为工厂方法或实际的工厂对象,但通常这不会是您的第一个 goto。
推荐阅读
- vue.js - 为什么 vue-signature-pad 不能在模态中工作?
- python - Tesseract 无法识别验证码文本
- mongoose - mongoose .find() 显示很多信息
- azure-cognitive-search - 通过调用 REST 端点将字段映射添加到“base64Encode”索引字段不起作用:“找到没有类型名称的资源”
- go - 断点命中后,Go Delve (1.0.0-rc2) 在 Windows 上冻结
- sql - 有没有更好的方法:更新事务中的同一行
- python - 如何使用 .append 在循环中创建一个常量列表
- google-cloud-platform - Google DataProc 的 Jupyter 中的 Python 版本错误
- google-cloud-platform - 使用 Google AutoML 进行训练时出现管道超时错误
- php - 显示一个空的 json 而不是 []