Clojure - tests with strategy components

I am using an application using the Stuart Sierra component. As he states in README:

Having a consistent way of setting up and stalling all associated states with the application allows fast development cycles without restarting the JVM. It can also perform unit tests faster and more independent, since the cost of creating and running the system is low enough for each test to create a new instance of the system.

What would be your preferred strategy here? Something similar to JUnit oneTimeSetUp / oneTimeTearDown, or is it really between each test (similar to setUp / tearDown)?

And if between each test there is an easy way to start / stop the system for all tests (before and after) without repeating the code each time?

Edit : sample code to show what I mean

(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)

Note . Here I am talking about unit testing.

+4
source share
1 answer

I would write a macro that takes a system card and starts all components before running tests and stops all components after testing.

For example:

(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)))))

Running the test you should see how it looks like

====> start
====> do action
====> stop

Ran 1 tests containing 1 assertions.
0 failures, 0 errors.
0
source

Source: https://habr.com/ru/post/1614002/


All Articles