Fork me on GitHub
#sql
<
2021-02-27
>
richiardiandrea00:02:11

Hello again everyone, I am trying to unit test something via mocking (I know I know...), however, I don't know how to mock with-db-transaction...I tried mocking db-transaction* instead but it does not seem to work fine... What do other people do?

seancorfield00:02:09

I either use a local test DB that is setup/torn down around the test suite (after all, we have migrations for every change we've made to the DB schema so running all the migrations from scratch locally is "easy"). For each test, the necessary DB state is setup (and cleaned up afterward). Or... I mock out just the routine that would persist the changes.

seancorfield00:02:05

I guess I would ask: 1) what are you doing inside that transaction? 2) what else does that function that calls with-db-transaction do?

richiardiandrea00:02:04

I am ok with mocking around transactions for this. I really don't need that. All the other db functions are mocked with with-redefs at this point but with-db-transaction is also trying to do with-open and therefore I need to pass something that it likes 🙂

richiardiandrea00:02:39

I tried to with-redefs clojure.core/with-open but I felt very dirty 🙂

seancorfield00:02:47

I'm suggesting mocking the function in your code that is calling with-db-transaction instead.

seancorfield00:02:04

Of course, it needs to only run that transaction 🙂

richiardiandrea00:02:17

yeah..unfortunately that's the one under test

richiardiandrea00:02:39

so somewhere in the non-db logic there is something I need to test

richiardiandrea00:02:49

(it's a bit all tangled)

seancorfield00:02:00

Which is why I asked those questions. You should separate out the non-DB logic from the TX persistence piece then.

seancorfield00:02:16

Detangle it, and it becomes much more testable.

seancorfield00:02:34

(if something is hard to test, it's probably designed poorly)

richiardiandrea00:02:38

well it definitely is

richiardiandrea00:02:51

not sure I will have time to refactor it

richiardiandrea00:02:39

but thanks Sean I guess I got my answer...it's not possible to do much unit testing (via mocks) here - better go for some other strategy

seancorfield00:02:05

It may also help to remember that clojure.java.jdbc does not actually nest TX (because it's not supported by DBs), so you could have a test fixture that set up a TX, called the test, and then rolled back the TX. At that point, any TX that the code tries to set up as part of executing the test is just going to be ignored. That may not be the right semantic for you, but it's available as an option.

seancorfield00:02:12

(note: next.jdbc behaves differently there -- it deliberately allows you to overlap TX scopes but assumes you know what you're doing! you can get both the c.j.j behavior and a prohibition on attempts to nest TX -- by rebinding next.jdbc.transaction/*nested-tx*)

👍 3