【问题标题】:Good practices to test piece of code with object instantiation使用对象实例化测试一段代码的良好实践
【发布时间】:2020-03-11 09:16:27
【问题描述】:

是否有任何指导方针(或最佳实践)来整理以下内容?

我有以下方法可以测试:

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
}

当我开始为这个函数编写单元测试时,我意识到:

  1. 测试线val profile = profileFactory.create(remoteProfile) 既简单又方便,因为我可以模拟此调用的结果并分别测试从remoteProfileprofile 的映射。有了这个,如果我改变映射的逻辑,我不会破坏我对 findProfileByPersonalInfo 的测试,这很好。
  2. 反之亦然,如果personalInfosearchParams的映射逻辑属于findProfileByPersonalInfo,感觉不太对也很难维护。

问题是:

  1. 是否可以(几乎)总是将实例化逻辑从被测函数中移出,以使其更易于测试和维护?毫无疑问,唯一的职责是实例化对象的函数是个例外。
  2. 为每个属于上述情况的对象创建某种类型的工厂是不是太过分了?系统的整体设计似乎因此受到影响。

非常感谢任何对最佳实践或讨论的引用。非常感谢你!

【问题讨论】:

    标签: java unit-testing testing kotlin


    【解决方案1】:
    1. 这有点宽泛,一般来说,您希望方法不要做太多事情,并将代码的可重用部分移动到单独的方法中。根据您展示的有限上下文,在这种情况下,出于可测试性和可读性的原因,我肯定会将实例移出。

    2. 你并不总是需要一个成熟的工厂,根据上下文一个简单的构造函数RemoteProfileSearchParameters(personInfo: PersonalInfo) 可能是最明智的。根据复杂性,这可能会被重构为工厂方法或实际工厂对象,但通常这不会是您的第一个 goto。

    【讨论】:

    • 感谢您的回复,我基本同意您的看法。但是在构造函数的情况下如何测试实例化逻辑(即使可以使用某些框架模拟构造函数,这是相当“不”)?
    • 您只需实例化该类的一个对象,并根据构造函数中提供的输入确认该对象的行为是否符合预期。模拟是没有意义的,因为你会模拟你想要测试的东西,从而测试你的模拟。如果在测试中调用构造函数是不可能的,例如由于外部依赖,那么你需要在你的主代码中注入这些依赖并在测试中模拟它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 2015-04-01
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多