简体   繁体   English

单元测试是否有异常

[英]Unit testing for exceptions

Can I write a test case with Test.HUnit that checks whether a call throws an exception? 我可以用Test.HUnit编写一个测试用例来检查调用是否引发异常吗?

I only care whether it throws any error, regardless of what message it prints. 无论打印什么消息,我都只关心它是否引发任何错误。

This isn't specific to HUnit, but you can write a function to check whether an IO value throws: 这不是特定于HUnit,但是您可以编写一个函数来检查IO值是否抛出:

λ> :set -XScopedTypeVariables
λ> import Control.Exception
λ> import Data.Functor
λ> import System.Environment

λ> throws io = catch (io $> False) $ \(e :: SomeException) -> pure True
throws :: IO a -> IO Bool

λ> sequence $ throws <$> [ getEnv "HOME", getEnv "whatever", error "a" ]
[False,True,True]

If by an "exception" you mean Exception and it is being thrown in some IO code, then you can use catch or catches . 如果“异常”是指Exception并且它正在某些IO代码中引发,则可以使用catchcatches However, if you mean catching things like error "Something bad happened" in pure code , you are out of luck. 但是,如果您要用纯代码捕获诸如error "Something bad happened" ,那么您就不走运了。 If you are willing to do the handling in IO , you have more options: 如果您愿意在IO进行处理,则有更多选择:

ghci> import Control.Exception
ghci> catch (error "Eek") (\(ErrorCallWithLocation msg _) -> putStrLn msg) 
Eek

From the Haskell 2010 report section 3 : 在Haskell 2010报告第3部分中

Errors during expression evaluation, denoted by ⊥ (“bottom”), are indistinguishable by a Haskell program from non-termination. Haskell程序将表达式评估过程中的错误用⊥(“底部”)表示,与未终止是无法区分的。

Here is another way to think about it: notice that the moment we try to evaluate a value that is ⊥ (like error "Help!" ) depends not on when this value was created but only when it was first needed (since Haskell is non-strict). 这是另一种思考方式:请注意,我们尝试评估⊥值的时间(例如error "Help!" )不取决于创建此值的时间而仅取决于首次使用它的时间(因为Haskell不是-严格)。 A mechanism to catch this sort of error would then break referential transparency. 捕获此类错误的机制将破坏参照透明性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM