如何在 Clojure 测试中测试预期异常的消息?
How to test the message of an expected exception in a Clojure test?
我有以下 Clojure 代码:
(defn is-valid-lang
[lang]
(.contains (list "ru" "en" "de") lang))
(defn s
[txt]
{
:desc txt
:lang "ru"
})
(defn s
[txt lang]
(if-not (is-valid-lang lang)
(throw (.IllegalArgumentException (format "'%s' is an invalid language." lang)))
{
:desc txt
:lang lang
}
)
)
我想编写一个测试来验证 s
抛出的异常消息,如果 lang
无效。
我写了这个:
(deftest s-lang-invalid-lang-test
(is
(thrown-with-msg?
IllegalArgumentException
#"'invalid-language' is an invalid language."
(s "something" "invalid-language")
)
)
)
由于以下错误,测试失败:
error {
:cause "No matching field found: IllegalArgumentException for class java.lang.String"
:via
[{:type java.lang.IllegalArgumentException
:message "No matching field found: IllegalArgumentException for class java.lang.String"
:at [clojure.lang.Reflector getInstanceField "Reflector.java" 397]}]
:trace
如果 s
抛出异常并显示正确消息,我该如何解决此问题并确保测试成功?
更新 1: 修复了 cfrick 指出的多参数问题。
(defn s
([txt]
{
:desc txt
:lang "ru"
})
([txt lang]
(if-not (is-valid-lang lang)
(throw (IllegalArgumentException. (format "'%s' is an invalid language." lang)))
{
:desc txt
:lang lang
})
)
)
您没有正确实例化 IllegalArgumentException。 Clojure 使用:
(IllegalArgumentException. "your message")
调用Java构造函数。参见 this article on Java interop
作为替代技术,您可以使用正则表达式搜索异常错误消息,如下所示:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn thrower
[lang]
(throw (ex-info "invalid language" {:lang lang})))
(dotest
(throws? (thrower "bogosity")) ; just verify it throws an exception, ignoring type and message
; `(throws? ...)` is a convenience fn from tupelo.test (also `dotest`)
(try
(thrower "bogosity")
(catch Exception e
(let [s (str e)]
(is (re-find #"invalid language" s)) ; returns "invalid language"
(is (re-find #"bogosity" s))) ; returns "bogosity"
)))
在单元测试中,搜索预期的字符串片段(例如异常错误消息中的 in)通常比进行字符串相等性比较更容易。完整的异常字符串是:
clojure.lang.ExceptionInfo: invalid language {:lang "bogosity"}
为了方便,我们使用tupelo.test library。函数 is-nonblank=
也很方便。
从tupelo.string开始,我们还有这些辅助函数:
- 小写=
- 非空行=
- 非空白=
- 包含匹配项?
- 包含-str?
- 引用->单
- 引号->双
以及许多其他使编写基于字符串的测试变得更加容易的方法。
我有以下 Clojure 代码:
(defn is-valid-lang
[lang]
(.contains (list "ru" "en" "de") lang))
(defn s
[txt]
{
:desc txt
:lang "ru"
})
(defn s
[txt lang]
(if-not (is-valid-lang lang)
(throw (.IllegalArgumentException (format "'%s' is an invalid language." lang)))
{
:desc txt
:lang lang
}
)
)
我想编写一个测试来验证 s
抛出的异常消息,如果 lang
无效。
我写了这个:
(deftest s-lang-invalid-lang-test
(is
(thrown-with-msg?
IllegalArgumentException
#"'invalid-language' is an invalid language."
(s "something" "invalid-language")
)
)
)
由于以下错误,测试失败:
error {
:cause "No matching field found: IllegalArgumentException for class java.lang.String"
:via
[{:type java.lang.IllegalArgumentException
:message "No matching field found: IllegalArgumentException for class java.lang.String"
:at [clojure.lang.Reflector getInstanceField "Reflector.java" 397]}]
:trace
如果 s
抛出异常并显示正确消息,我该如何解决此问题并确保测试成功?
更新 1: 修复了 cfrick 指出的多参数问题。
(defn s
([txt]
{
:desc txt
:lang "ru"
})
([txt lang]
(if-not (is-valid-lang lang)
(throw (IllegalArgumentException. (format "'%s' is an invalid language." lang)))
{
:desc txt
:lang lang
})
)
)
您没有正确实例化 IllegalArgumentException。 Clojure 使用:
(IllegalArgumentException. "your message")
调用Java构造函数。参见 this article on Java interop
作为替代技术,您可以使用正则表达式搜索异常错误消息,如下所示:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn thrower
[lang]
(throw (ex-info "invalid language" {:lang lang})))
(dotest
(throws? (thrower "bogosity")) ; just verify it throws an exception, ignoring type and message
; `(throws? ...)` is a convenience fn from tupelo.test (also `dotest`)
(try
(thrower "bogosity")
(catch Exception e
(let [s (str e)]
(is (re-find #"invalid language" s)) ; returns "invalid language"
(is (re-find #"bogosity" s))) ; returns "bogosity"
)))
在单元测试中,搜索预期的字符串片段(例如异常错误消息中的 in)通常比进行字符串相等性比较更容易。完整的异常字符串是:
clojure.lang.ExceptionInfo: invalid language {:lang "bogosity"}
为了方便,我们使用tupelo.test library。函数 is-nonblank=
也很方便。
从tupelo.string开始,我们还有这些辅助函数:
- 小写=
- 非空行=
- 非空白=
- 包含匹配项?
- 包含-str?
- 引用->单
- 引号->双
以及许多其他使编写基于字符串的测试变得更加容易的方法。