gpt4 book ai didi

unit-testing - 如何使此功能可测试?

转载 作者:行者123 更新时间:2023-12-03 09:27:38 25 4
gpt4 key购买 nike

我有一个功能负责收集一堆配置并从所有这些部分中制作更大的配置。所以基本上是:

let applyUpdate updateData currentState =
if not (someConditionAbout updateData) then
log (SomeError)

let this = getThis updateData currentState.Thingy
let that = getThat updateData currentState.Thingy
let andThat = createThatThing that this updateData

// blablablablablabla

{ currentState with
This = this
That = that
AndThat = andThat
// etc. }

我目前有 getThis 的单元测试, getThat , createThatThing ,但不适用于 applyUpdate .我不想重新测试 getThis等等正在做,我只是想测试特定于 applyUpdate 的逻辑并且只是 stub getThis .在面向对象的风格中,这些将通过依赖注入(inject)通过接口(interface)传递。在功能风格中,我不确定如何进行:
// This is the function called by tests
let applyUpdateTestable getThisFn getThatFn createThatThingfn etc updateData currentState =
if not (someConditionAbout updateData) then
log (SomeError)

let this = getThisFn updateData currentState.Thingy
// etc

{ currentState with
This = this
// etc. }

// This is the function that is actually called by client code
let applyUpdate = applyUpdateTestable getThis getThat etc

这似乎与 SCSS 注入(inject)的功能等效,但除此之外,我主要关心的是:
  • 现在我的代码更难遵循,因为你不能只是 F12 (Go
    到定义)成函数;这个问题也存在
    OO 依赖注入(inject),但通过工具(即 Resharper Go
    实现)。
  • 我正在测试的函数在技术上不是生产代码调用的函数(映射中可能存在错误)
  • 我什至没有看到函数
  • 的“可测试”版本的好名字。
  • 我用重复的定义污染了模块

  • 在函数式编程中如何处理这些问题?

    最佳答案

    你说:

    In an object-oriented style, these would be passed via an interface through dependency injection.



    在 FP 中使用了相同的方法,但不是通过对象构造函数注入(inject),而是“注入(inject)”作为函数的参数。

    因此,您的 applyUpdateTestable 走在正确的轨道上,除了这也将用作真正的代码,而不仅仅是可测试的代码。

    例如,这是传入三个额外依赖项的函数:
    module Core =   
    let applyUpdate getThisFn getThatFn createThatThingfn updateData currentState =
    if not (someConditionAbout updateData) then
    log (SomeError)

    let this = getThisFn updateData currentState.Thingy
    // etc

    { currentState with
    This = this
    // etc. }

    然后,在“生产”代码中,注入(inject)真正的依赖项:
    module Production =         
    let applyUpdate updateData currentState =
    Core.applyUpdate Real.getThis Real.getThat Real.createThatThingfn updateData currentState

    或者更简单地说,使用部分应用:
    module Production =         
    let applyUpdate =
    Core.applyUpdate Real.getThis Real.getThat Real.createThatThing

    在测试版本中,您注入(inject)了模拟或 stub :
    module Test =       
    let applyUpdate =
    Core.applyUpdate Mock.getThis Mock.getThat Mock.createThatThing

    在上面的“生产”示例中,我对 Real 上的依赖项进行了静态硬编码。功能,但或者,
    就像 OO 风格的依赖注入(inject)一样,产生式 applyUpdate可以由一些顶级协调员创建
    然后传递给需要它的函数。

    这回答了你的问题,我希望:
  • 生产和测试使用相同的核心代码
  • 如果您对依赖项进行静态硬编码,您仍然可以使用 F12 来深入了解它们。

  • 这种方法有更复杂的版本,例如“Reader”monad,但上面的代码是最简单的方法。

    Mark Seemann 有很多关于这个主题的好帖子,例如 Integration TestingSOLID: the next step is FunctionalPorts and Adapters .

    关于unit-testing - 如何使此功能可测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38663990/

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