F# 在FsUnit';中,我如何可以忽略有区别的联合案例的值;谁断言?

F# 在FsUnit';中,我如何可以忽略有区别的联合案例的值;谁断言?,f#,fsunit,F#,Fsunit,我怎么能在FsUnit的断言中忽略一个有区别的联合案例的值呢 例如: type TransactionAttempt = { Deposited:float Requires:float } type RequestResult = | Denied of TransactionAttempt | Granted of Product 在我的测试中,我想这样做: let display = balance |> select Pepsi displa

我怎么能在FsUnit的断言中忽略一个有区别的联合案例的值呢

例如:

type TransactionAttempt = { 
    Deposited:float
    Requires:float 
}

type RequestResult =
    | Denied of TransactionAttempt
    | Granted of Product
在我的测试中,我想这样做:

let display = balance |> select Pepsi
display |> should equal Denied
display |> should equal (Denied {Deposited=0.25; Requires=1.00})
我不介意这样做:

display |> should equal (Denied _)
然而,我不得不这样做:

let display = balance |> select Pepsi
display |> should equal Denied
display |> should equal (Denied {Deposited=0.25; Requires=1.00})
请注意,我对上述表达式的理解必须非常明确。

因此,我只想知道它是否被拒绝。我不在乎细节

以下是实际测试:

[<Test>]
let ``Vending machine reflects more money required for selection``() =
   // Setup
   let balance = Quarter |> insert []

   // Test
   let display = balance |> select Pepsi

   // Verify
   display |> should equal (Denied {Deposited=0.25; Requires=1.00})
以下是整个域:

module Machine

type Deposit =
    | Nickel
    | Dime
    | Quarter
    | OneDollarBill
    | FiveDollarBill

type TransactionAttempt = { 
    Deposited:float
    Requires:float 
}

type State =
    | OutOfService
    | PaymentReceived of Deposit
    | WaitingForSelection
    | NotPaidInFull of TransactionAttempt

type Product =
    | Pepsi
    | Coke
    | Sprite
    | MountainDew

type RequestResult =
    | Denied of TransactionAttempt
    | Granted of Product

(* Functions *)
open System

let display = function
    | OutOfService            -> "Out of Service"
    | WaitingForSelection     -> "Make selection"
    | NotPaidInFull attempt   -> sprintf "%s Required" ((attempt.Requires - attempt.Deposited).ToString("C2"))
    | PaymentReceived deposit -> match deposit with
                                 | Nickel         -> "5¢"
                                 | Dime           -> "10¢"
                                 | Quarter        -> "25¢"
                                 | OneDollarBill  -> "$1.00"
                                 | FiveDollarBill -> "$5.00"

let getBalance coins =
    coins |> List.fold (fun acc d -> match d with
                                     | Nickel         -> acc + 0.05
                                     | Dime           -> acc + 0.10
                                     | Quarter        -> acc + 0.25
                                     | OneDollarBill  -> acc + 1.00
                                     | FiveDollarBill -> acc + 5.00) 0.00
let insert balance coin =
    coin::balance |> getBalance

let getPrice = function
    | Pepsi       -> 1.00
    | Coke        -> 1.00
    | Sprite      -> 1.00
    | MountainDew -> 1.00

let select product balance =
    let attempt = { Deposited=balance
                    Requires=product |> getPrice }

    let paidInFull = attempt.Deposited >= attempt.Requires

    if not paidInFull then 
        Denied attempt
    else Granted product

我能想到的最简单的方法是为您想要的支票编写一个谓词:

let isDenied du =
    match du with
    | Denied _ -> true
    | _ -> false
或者,由于
让f x=将x与…
匹配等同于
让f=函数…
,这可能是:

let isDenied = function Denied _ -> true | _ -> false
然后,您的测试如下所示:

display |> isDenied |> should be True
请注意,
True
,带大写字母T,是一个约束条件。如果与布尔值进行比较,那么

display |> isDenied |> should equal true
如果您发现必须编写大量这些自定义谓词,那么可能有一种更通用的解决方案,包括为NUnit或XUnit或您在后端使用的任何测试框架编写自定义约束。但是作为F#的相对新手,您可能应该首先使用简单的解决方案,然后对其进行推广


另外,如果您决定编写自定义约束,请查看(如果您使用的是NUnit)或(如果您使用的是XUnit)以获得灵感。

由@rmunn给出的答案看起来不错,但是
display |>的错误应该是相同的(拒绝{deposition=0.25;Requires=1.00}
?应该
拒绝{deposition=0.22;Requires=1.04}
通过测试吗?谢谢。你说得对。