为什么我不能使用midje来模拟使用弹弓投掷+抛出的函数

时间:2013-06-12 15:35:18

标签: unit-testing exception-handling clojure mocking midje

这是情况:我正在尝试单元测试函数A调用函数B.函数B在弹弓try + block中调用,在某些情况下它可以使用弹弓投掷+。我想在midje测试中模拟函数B,以便返回try + block中的catch实际捕获的内容。我似乎无法创造出正确的东西。这是代码和测试的大致缩略图:

(defn function-A
  [param]
  (try+
    (function-B param)
    (catch [:type :user-not-found]
      (do-something))))

(defn function-B
  [param]
  (throw+ [:type :user-not-found]))

(fact "do-something is called"
  (function-A "param") => (whatever is the result of calling do-something)
  (provided
    (function-B "param") =throws=> (clojure.lang.ExceptionInfo. "throw+: {:type :user-not-found}"
                                                                {:object {:type :user-not-found}, :environment {}}
                                                                nil)))

我投掷的异常信息似乎是正确的。当我的应用程序通过大量的prn语句运行时,我可以看到这一点。但是,无论我尝试什么,我都无法让测试工作。

我还在repl中尝试了下面的代码,看看我是否能理解这个问题。然而,虽然两段代码似乎都涉及相同的异常,但只有一个(纯粹的弹弓)设法捕获并打印“抓住它”。我想如果我能理解为什么一个有效而另一个无法有效,我就可以通过单元测试解决问题。

(try+
  (try
    (throw+ {:type :user-not-found})
    (catch Exception e
      (prn "Caught:  " e)
      (prn "Class:   " (.getClass e))
      (prn "Message: " (.getMessage e))
      (prn "Cause:   " (.getCause e))
      (prn "Data:    " (.getData e))
      (throw e)))
  (catch [:type :user-not-found] p
    (prn "caught it")))

(try+
  (try
    (throw (clojure.lang.ExceptionInfo. "throw+: {:type :user-not-found}"
                                        {:object {:type :user-not-found}, :environment {}}
                                        nil))
    (catch Exception e
      (prn "Caught:  " e)
      (prn "Class:   " (.getClass e))
      (prn "Message: " (.getMessage e))
      (prn "Cause:   " (.getCause e))
      (prn "Data:    " (.getData e))
      (throw e)))
  (catch [:type :user-not-found] p
    (prn "caught it")))

2 个答案:

答案 0 :(得分:4)

这是一个非常晚的回应,但下面的解决方案呢:

    <!doctype html>
    <html>
    <head>
      <meta charset=utf-8>
      <title>SelectBoxIt demo</title>
      <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css" />
      <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/themes/base/jquery-ui.css" />
      <link type="text/css" rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
      <link rel="stylesheet" href="http://gregfranko.com/jquery.selectBoxIt.js/css/jquery.selectBoxIt.css" />
    </head>
    <body>

      <select name="test">
        <option value="SelectBoxIt is:">SelectBoxIt is:</option>
        <option value="a jQuery Plugin">a jQuery Plugin</option>
        <option value="a Select Box Replacement">a Select Box Replacement</option>
        <option value="a Stateful UI Widget">a Stateful UI Widget</option>
      </select>

      <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
      <script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js"></script>
      <script src="http://gregfranko.com/jquery.selectBoxIt.js/js/jquery.selectBoxIt.min.js"></script>
      <script>
        $(function() {

          var selectBox = $("select").selectBoxIt();

        });
      </script>
    </body>
    </html>

用法示例:

<input type="text" name="username" value="{{ old('username') }}">

好处是你不依赖Slingshot的内部实施。

答案 1 :(得分:2)

按照弹弓的代码生成一个throwable(参见hereherehere),我找到了以下(有点人为的)生成throwable的方法只是throw ing。

(s/get-throwable (s/make-context {:type :user-not-found} "throw+: {:type :user-not-found}" (s/stack-trace) {}))

它会呈现您期望从您的示例中得到的结果。

(try+
  (try
    (throw (s/get-throwable (s/make-context {:type :user-not-found} "throw+: {:type :user-not-found}" (s/stack-trace) {})))
    (catch Exception e
      (prn "Caught:  " e)
      (prn "Class:   " (.getClass e))
      (prn "Message: " (.getMessage e))
      (prn "Cause:   " (.getCause e))
      (prn "Data:    " (.getData e))
      (throw e)))
  (catch [:type :user-not-found] p
    (prn "caught it")))

希望它有所帮助。