我有一个功能:
unify :: [Constraint] -> [Substitution]
Run Code Online (Sandbox Code Playgroud)
在某些情况下,它会抛出error函数的异常:
error "Circular constraint"
Run Code Online (Sandbox Code Playgroud)
我正在使用Test.HUnit单元测试,我想制作一个测试用例,声明这些错误会被抛出某些输入.我找到了这个,它提供了一种测试异常的方法,这些异常是实例Eq,但error似乎是一个ErrorCall异常,它不是一个实例Eq,所以我得到了错误:
No instance for (Eq ErrorCall)
arising from a use of `assertException'
Run Code Online (Sandbox Code Playgroud)
如何编写被调用的TestCase断言error并且(最好)检查消息?
理想情况下,我会将您的功能重构为
unify' :: [Constraint] -> Maybe [Substitution]
unify' = -- your original function, but return Nothing instead of calling error,
-- and return Just x when your original function would return x
unify = fromMaybe (error "Circular constraint") . unify'
Run Code Online (Sandbox Code Playgroud)
然后我会测试unify'而不是测试unify.
如果有多个可能的错误消息,我会像这样重构它:
unify' :: [Constraint] -> Either String [Substitution]
-- and return Left foo instead of calling error foo
unify = either error id . unify'
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,如果这是其他程序员将使用的库,他们中的一些人宁愿调用unify'而不是部分函数unify.)
如果您无法重构代码,我会修改您链接的代码,替换assertException为:
assertErrorCall :: String -> IO a -> IO ()
assertErrorCall desiredErrorMessage action
= handleJust isWanted (const $ return ()) $ do
action
assertFailure $ "Expected exception: " ++ desiredErrorMessage
where isWanted (ErrorCall actualErrorMessage)
= guard $ actualErrorMessage == desiredErrorMessage
Run Code Online (Sandbox Code Playgroud)