4

私は機能を持っています:

unify :: [Constraint] -> [Substitution]

場合によっては、次のerror関数で例外をスローします。

error "Circular constraint"

私はTest.HUnit単体テストに使用していますが、これらのエラーが特定の入力でスローされることを主張するテスト ケースを作成したいと考えています。のインスタンスである例外をテストする方法を提供するthisを見つけましたEqが、 のインスタンスではない例外error与えるように見えるため、エラーが発生します。ErrorCallEq

No instance for (Eq ErrorCall)
  arising from a use of `assertException'

TestCase呼び出されたことをアサートしerror、(できれば) メッセージをチェックするa を作成するにはどうすればよいですか?

4

1 に答える 1

6

理想的には、関数をリファクタリングします

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'

次に、テストunify'の代わりにテストしますunify

考えられるエラー メッセージが複数ある場合は、代わりに次のようにリファクタリングします。

unify' :: [Constraint] -> Either String [Substitution]
    -- and return Left foo instead of calling error foo

unify = either error id . unify'

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
于 2012-11-29T17:33:48.337 に答える