试图汇总一些断言功能,我无法尝试工作



我只是在学习f#,所以我正在尝试一些事情(我知道可以只使用Xunit或其他东西)

我有以下断言方法,其想法是,它应该采取预期的例外和期望引发此例外的功能,然后执行函数和内部测试,如果抛出的异常与预期的。

let assertException (testName : string) (expected : 'a when 'a :> Exception) functionToBeTested =
    try
        functionToBeTested
        (false)
    with
    | :? Exception as someException when someException :? expected ->
            printTestResultInMiddle (sprintf "Test: %s PASSED: Raised expected exception %A" testName expected) true 
            (true)
    | _ ->
        printTestResultInMiddle (sprintf "Test: %s FAILED: expected exception %A" testName expected) false
        (false)

它在我尝试调用打印方法的行中给了我错误的 Unexpected symbol '(' in pattern matching. Expected '->' or other token.。我不应该将此try ... with视为

match ... with

??

还有另一个问题,我可以更轻松吗?

首先,
您正在尝试将类型查询操作员:?与类型'a的值expected一起使用。该操作员不能仅与值一起使用:

let x = box 5
let a = x :? int    // true
let b = x :? string // false
let y = 10
let c = x :? y  // error: type 'y' is not defined

在您的示例中(处理异常),这将是这样的:

someException :? InvalidOperationException

或,如果要与类型参数进行比较:

someException :? 'a

第二
如果您要做的只是比较它的类型,为什么还要给someException的名字呢?这正是with | :?子句首先要做的:

try
    ...
with
| :? 'a ->
   ...

然后,您实际上不需要值expected,因为您要探测的只是类型。因此,您可以声明通用参数并取消常规参数:

let assertException<'a> (testName : string) functionToBeTested =
   ...

,最后,
您的functionToBeTested实际上不是一个函数,因为您没有调用它。如果要验证执行过程中它会引发特定异常,则需要实际拨打电话:

        functionToBeTested()

将它们放在一起:

let assertException<'a when :> exn> (testName : string) functionToBeTested =
    try
        functionToBeTested()
        (false)
    with
    | :? 'a ->
            printTestResultInMiddle (sprintf "Test: %s PASSED: Raised expected exception %A" testName typeof<'a>.Name) true 
            (true)
    | _ ->
        printTestResultInMiddle (sprintf "Test: %s FAILED: expected exception %A" testName typeof<'a>.Name) false
        (false)

显然您需要在when表达式周围放置括号。您需要对expected类型进行检查,即'a。以下内容应编译(当我用printfn替换您的printTestResultInMiddle调用时,它对我有用):

let assertException (testName : string) (expected : 'a when 'a :> Exception) functionToBeTested =
    try
        functionToBeTested
        (false)
    with
    | :? Exception as someException when (someException :? 'a) ->
            printTestResultInMiddle (sprintf "Test: %s PASSED: Raised expected exception %A" testName expected) true 
            (true)
    | _ ->
        printTestResultInMiddle (sprintf "Test: %s FAILED: expected exception %A" testName expected) false
        (false)

但是,这给:? Exception as someException表达式发出警告:

警告FS0067:这种类型的测试或降低将始终保持

那是因为根据try ... with文档,裸露标识符等效于:? System.Exception as <identifier>。因此,您可以将功能简化为:

let assertException (testName : string) (expected : 'a when 'a :> Exception) functionToBeTested =
    try
        functionToBeTested
        (false)
    with
    | someException when (someException :? 'a) ->
            printTestResultInMiddle (sprintf "Test: %s PASSED: Raised expected exception %A" testName expected) true 
            (true)
    | _ ->
        printTestResultInMiddle (sprintf "Test: %s FAILED: expected exception %A" testName expected) false
        (false)

但实际上,这样做更简单:

let assertException (testName : string) (expected : 'a when 'a :> Exception) functionToBeTested =
    try
        functionToBeTested
        (false)
    with
    | :? 'a ->
            printTestResultInMiddle (sprintf "Test: %s PASSED: Raised expected exception %A" testName expected) true 
            (true)
    | _ ->
        printTestResultInMiddle (sprintf "Test: %s FAILED: expected exception %A" testName expected) false
        (false)

当我在f#Interactive中尝试时也会编译,尽管我实际上并未对其进行测试。我确实注意到您的try表达式中的functionToBeTested可能应该是函数调用(即functionToBeTested ()。您不需要(true)(false)表达式周围的括号。

因此,您可以做的另一种迭代,尽我所能,而无需更改其语义(并注意i at 使用functionToBeTested ()稍微更改其语义)将是:

let assertException (testName : string) (expected : 'a when 'a :> Exception) functionToBeTested =
    try
        functionToBeTested ()
        false
    with
    | :? 'a ->
            printTestResultInMiddle (sprintf "Test: %s PASSED: Raised expected exception %A" testName expected) true 
            true
    | _ ->
        printTestResultInMiddle (sprintf "Test: %s FAILED: expected exception %A" testName expected) false
        false

最新更新