为符号`with-redefs`连续返回不同的值(Clojure)

时间:2018-01-22 03:28:29

标签: unit-testing clojure

我希望使用with-redefs来模拟STDIN的用户输入。

首先,我正在测试不正确的输入,应该重新询问用户输入。然后,应该给出正确的输入。

有没有办法使用with-redefs将不同的值绑定到给定的符号?

我试图获得此功能:

(with-redefs [read-line (fn [] "HI")
              read-line (fn [] "OK")]
  (do (println (read-line)) ;; -> "HI"
      (println (read-line)))) ;; -> "OK"

3 个答案:

答案 0 :(得分:7)

不是特别的,但是你总是可以用某种状态'让兰比达'过来!

(let [a (atom ["a" "b"])]
  (defn f []
    (let [r (first @a)]
      (swap! a rest)
      r)))

(f) ;; "a"
(f) ;; "b"
(f) ;; nil

在你的特定情况下,有一个生成'有状态'函数的函数是有意义的,所以一个完整的例子是:

(defn maker [l]
  (let [a (atom l)]
    (fn []
      (let [r (first @a)]
        (swap! a rest)
        r))))

(with-redefs [read-line (maker ["HI" "OK"])]
  (do (println (read-line)) ;; -> "HI"
      (println (read-line)))) ;; -> "OK"

答案 1 :(得分:4)

为此目的,您可能会更乐意使用with-in-str

  (with-in-str "Hello"
    (println (read-line)))
  (with-in-str "There"
    (println (read-line))))

结果:

(read-line) => "Hello"
(read-line) => "There"

请务必始终向The Clojure Cheatsheet打开浏览器标签,并经常仔细阅读!

答案 2 :(得分:0)

以下是我认为可能有用的代码示例:

(ns project.test
  (:require [clojure.test :refer :all]))

(deftest test-user-input

  (testing "wrong input"
    (with-in-str "some wrong input"
      (is (thrown?
           SomeExceptionClass
           (call-your-function)))))

  (testing "correct input"
    (with-in-str "some correct input"
      (let [result (call-your-function)]
        (is (= result [:proper :data]))))))