gpt4 book ai didi

f# - 如何在 f# 中使用外部依赖项测试函数

转载 作者:行者123 更新时间:2023-12-03 09:49:05 24 4
gpt4 key购买 nike

我很难尝试对具有外部依赖项的 F# 代码进行单元测试。

在 C#(我的背景)中,您通常会有一个传入依赖项的类,然后重新使用它。为我的示例代码道歉,这很愚蠢,但我只是想说明我的观点。

public class Foo {

IDependency d;
public Foo(IDependency d) { this.d = d; }

public int DoStuff(string bar) { return d.DoSomethingToStuff(bar); }

public int DoMoreStuff(string bar) {
int i = d.DoSomethingToStuff(bar);
return d.DoSomethingElseToStuff(bar, i);
}
}

我试图以务实的态度使用 F#,并避免使用类和接口(interface)(除非我需要与其他 .NET 语言进行互操作)。

所以我在这种情况下的方法是让模块和一些函数将依赖项作为函数传入。我发现了这个技术 here
module Foo

let doStuff bar somethingFunc =
somethingFunc bar

let doMoreStuff bar somethingFunc somethingElseFunc =
let i = somethingFunc bar
somethingElseFunc bar i

我对这段代码的两个问题是:
  • 我需要继续传递我的依赖关系。在 C# 中,它在构造函数中传递并重用。你可以想象如果 somethingFunc 会以多快的速度失控。在几个地方使用。
  • 如何对已执行的依赖项进行单元测试?再次在 C# 中,我将使用模拟框架并断言调用了某些方法。

  • 我如何在 F# 世界中解决这些问题?

    最佳答案

    不太难mapping SOLID concepts like Dependency Injection to Functional-style F# - 关键之一是意识到有一个 strong relationship between objects and closures .

    在本例中,对函数参数进行重新排序以使“依赖项”首先出现会有所帮助:

    module Foo =    
    let doStuff somethingFunc bar =
    somethingFunc bar

    let doMoreStuff somethingFunc somethingElseFunc bar =
    let i = somethingFunc bar
    somethingElseFunc bar i

    这将使您能够使用 组合函数部分函数应用 :
    let doStuff' = Foo.doStuff somethingImp

    现在, doStuff'是一个闭包,因为它关闭了具体函数 somethingImp .从本质上讲,它捕获了依赖关系,因此它就像一个具有注入(inject)依赖关系的对象一样工作,您仍然可以使用剩余的 bar 调用它争论:
    let bar = 42
    let actual = doStuff' bar

    测试

    以下是使用本地函数作为 stub 的示例:
    module Tests =

    let ``Data flows correctly through doMoreStuff`` () =
    let somethingFunc bar =
    assert (bar = 42)
    1337
    let somethingElseFunc bar i =
    assert (bar = 42)
    assert (i = 1337)
    "Success"

    let actual = Foo.doMoreStuff somethingFunc somethingElseFunc 42

    assert (actual = "Success")

    在这里,为了简单起见,我使用了 assert keyword ,但是为了正确的测试,你应该定义一个正确的断言函数,或者使用你最喜欢的断言库。

    通常,我倾向于放松对输入参数的验证,因为它可能会使测试替身与特定实现的耦合过于紧密。另外,请记住,您应该 use Stubs for Queries, and Mocks for Commands - 在这个例子中,只有查询,所以所有的测试替身都是 stub :虽然它们在被调用时会验证输入,但测试根本不会验证它们是否被调用。

    关于f# - 如何在 f# 中使用外部依赖项测试函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25195865/

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