2015-11-01 65 views
4

我正在使用Stuart Sierra組件實現一個應用程序。Clojure - 用組件策略測試

有一個連貫的方式來建立和拆除與應用程序相關 能夠快速的開發週期中的所有狀態而不 重新啓動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

我會寫一個宏,它會在運行測試之前獲取系統映射並啓動所有組件,並在測試之後停止所有組件。

例如:

(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))) 
      [email protected]) 
     (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.