我正在使用Stuart Sierra组件实现一个应用程序。正如他在自述文件中所述:
有一个连贯的方式来建立和拆除所有相关的状态 使用应用程序可以实现快速开发周期 重新启动JVM。它还可以使单元测试更快,更多 因为创建和启动系统的成本很低,所以是独立的 足以让每个测试都能创建一个新的系统实例。
这里的首选策略是什么?类似于JUnit oneTimeSetUp / oneTimeTearDown的东西,还是真的在每个测试之间(类似于setUp / tearDown)?
如果在每次测试之间,是否有一种简单的方法来启动/停止所有测试(之前和之后)的系统,而不是每次都重复代码?
编辑:示例代码以显示我的意思
(defn test-component-lifecycle [f]
(println "Setting up test-system")
(let [s (system/new-test-system)]
(f s) ;; I cannot pass an argument here ( https://github.com/clojure/clojure/blob/master/src/clj/clojure/test.clj#L718 ), so how can I pass a system in parameters of a test ?
(println "Stopping test-system")
(component/stop s)))
(use-fixtures :once test-component-lifecycle)
注意:我在这里讨论单元测试。
答案 0 :(得分:0)
我会编写一个宏,它接受系统映射并在运行测试之前启动所有组件,并在测试后停止所有组件。
例如:
(ns de.hh.new-test
(:require [clojure.test :refer :all]
[com.stuartsierra.component :as component]))
;;; Macro to start and stop component
(defmacro with-started-components [bindings & body]
`(let [~(bindings 0) (component/start ~(bindings 1))]
(try
(let* ~(destructure (vec (drop 2 bindings)))
~@body)
(catch Exception e1#)
(finally
(component/stop ~(bindings 0))))))
;; Test Component
(defprotocol Action
(do-it [self]))
(defrecord TestComponent [state]
component/Lifecycle
(start [self]
(println "====> start")
(assoc self :state (atom state)))
(stop [self]
(println "====> stop"))
Action
(do-it [self]
(println "====> do action")
@(:state self)))
;: TEST
(deftest ^:focused component-test
(with-started-components
[system (component/system-map :test-component (->TestComponent"startup-state"))
test-component (:test-component system)]
(is (= "startup-state" (do-it test-component)))))
跑步测试你应该看到像这样的输出
====> start
====> do action
====> stop
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.