Closed kendagriff closed 9 years ago
It depends what type of testing you're aiming to do.
If you want to perform an integration test against a real database, you can include the database component you're using in your tests. For example:
(deftest test-signup
(let [db (component/start (hikaricp/hikaricp {...}))]
(try
(let [handler (signup/signup-endpoint {:db db})]
...)
(finally
(component/stop db)))))
If you want to perform a unit test, then you need some way of mocking the database calls. Fortunately, components are records, and we can therefore extend them with protocols. For example, we might use the following protocol to abstract the signup database calls:
(defprotocol SignupModel
(create-user [db email password]))
In our real code, we implement the protocol for the database component:
(extend-protocol SignupModel
hikaricp/HikariCP
(create-user [{db-spec :spec} email password]
(jdbc/insert! db-spec ...)))
While in our test, we'd either use reify
or create a fake record:
(defrecord FakeDatabase
SignupModel
(create-user [_ _ _] 123))
Ah, thanks! I overlooked the obvious fact that components can be brought together without system-map
. Thanks for the examples!
What's the most appropriate way to test an endpoint component that has additional dependencies?
A standalone endpoint can be easily tested:
But how does that translate to endpoints that need, say, a database passed to its config? Shall I plan on
(start)
ing and(stop)
ing a complete system within each test?(P.S. Fantastic project, by the way – I'm planning to use it extensively in a microservices architecture, and I hope to contribute to it soon.)