2016-12-13 147 views
0

我可以编写一个测试用例Test.HUnit来检查一个调用是否引发异常?单元测试异常

我只关心它是否会抛出任何错误,无论它打印什么信息。

回答

2

这是不特定于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] 
+0

这也适用于'错误'? – cberkay

+0

是的,假设你使用'error'来产生'IO'类型的值。我已经更新了包含这个的答案。 –

+0

谢谢。我可能错过了一些明显的东西,但是当我将代码输入到repl中时,我得到'throws io = ...'的错误: '非法类型签名:'SomeException' 类型签名只允许在具有ScopedTypeVariables的模式中 – cberkay

2

如果一个“例外”你的意思是Exception,它是在一些IO抛出代码,那么你可以使用。但是,如果您的意思是在纯代码中捕获诸如error "Something bad happened"之类的内容,那么您运气不好。如果你愿意做处理中IO,你有更多的选择:

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

从哈斯克尔2010年报告section 3:表达式计算过程

错误,请⊥(“底部标示“),无法通过Haskell程序区分未终结。

这里是另一种方式来想一想:你会注意到现在我们试图评估值是⊥(如error "Help!")并不取决于当这个值创建但只有当它是第一需要(因为Haskell不严格)。捕捉这种错误的机制会破坏参照透明性。

+0

我明白了。不幸的是,我需要它的'错误'的情况。 – cberkay

+0

@cberkay已添加。只要你愿意接触'IO' monad,这是可能的。 – Alec