Clojure测试中如何为接收文件的代码模拟stdin字符串输入
方案1:核心逻辑抽离(最推荐)
你当前的写法把输入源解析和业务逻辑耦合在了-main入口里,最优解是把纯业务逻辑抽成独立函数,完全和输入来源解绑:
;; 抽离核心处理逻辑:接收行序列作为输入,直接处理输出 (defn process-lines [lines] (print-all (input-received lines))) ;; -main 只负责处理入口参数,适配不同输入源 (defn -main [& args] (process-lines (-> (or (first args) *in*) clojure.java.io/reader line-seq)))
测试的时候直接调用纯逻辑函数,不需要绕文件或者stdin绑定,写法最简洁:
(testing "Create account" (let [input "{\"account\": {\"active-card\": true, \"available-limit\": 100}}" expected (str (cheshire/generate-string {:account {:active-card true :available-limit 100} :violations []}) \newline)] (is (= expected (with-out-str (process-lines [input]))))))
方案2:兼容字符串输入的最小修改
如果不想调整现有代码结构,只需要修改read-input!函数,让它能区分输入是文件路径还是JSON内容即可:
(defn read-input! [input] (line-seq (clojure.java.io/reader ;; 判断输入是JSON内容还是文件路径,你也可以按自己的业务规则调整判断条件 (if (.startsWith (str input) "{") (java.io.StringReader. input) input))))
修改后你期望的测试写法可以直接运行,不需要额外调整:
(testing "Create account" (is (= (str (cheshire/generate-string {:account {:active-card true :available-limit 100} :violations []}) \newline) (with-out-str (io/-main "{\"account\": {\"active-card\": true, \"available-limit\": 100}}")))))
关于你自己摸索的方案
你用with-in-str绑定stdin的方案是可以正常运行的,缺点是需要操作全局输入流绑定,多测试用例并行执行时可能有冲突风险,同时嵌套层数更多,不如抽离纯逻辑的方案简洁易维护。
内容的提问来源于stack exchange,提问作者brenobarreto
相关产品推荐
相关产品推荐

