试图组合一些断言函数,但我无法尝试工作
Trying to put together a few assertion functions and i cannot get a try with to work
我只是在学习 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
??
还有一个问题,我可以更轻松地做到这一点吗?
显然您需要在此处将 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
表达式上发出警告:
warning FS0067: This type test or downcast will always hold
那是因为根据 try ... with
documentation,裸标识符等同于 :? 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)
表达式任.
所以你的代码再迭代一次,尽可能简单而不改变它的语义(注意我已经稍微改变了它的语义 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
第一,
您正在尝试将类型查询运算符 :?
与类型 '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)
我只是在学习 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
??
还有一个问题,我可以更轻松地做到这一点吗?
显然您需要在此处将 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
表达式上发出警告:
warning FS0067: This type test or downcast will always hold
那是因为根据 try ... with
documentation,裸标识符等同于 :? 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)
表达式任.
所以你的代码再迭代一次,尽可能简单而不改变它的语义(注意我已经稍微改变了它的语义 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
第一,
您正在尝试将类型查询运算符 :?
与类型 '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)