Live data from Hacker News

Database mocks are not worth it

shayon.dev

191–200 of 268 posts

Re: Database mocks are not worth it

#191

No... for pete sake no! The whole point of mocks for data base is not to test schema changes, it's to test a unit of code. These most certainly do not change the additional requirement of integration testing with real database tables. That usually happens after all the unit tests, obviously, because why spin up a big heavy database test pipeline if the code logic fails.

Nobody cares about your precious units they care that the system works. Thus you should test units that are as large as possible. That way if you add a feature you know the old ones didn't break. I've seen too many bugs where all the unit tests passed. If you are doing TDD 1000 integration test failures are no problem - the last thing you changed broke them all: either undo or fix it.

the only reason to write a unit test is if the integration test would run too long.

Re: Database mocks are not worth it

#192
post #66

Earlier quoted context omitted.

Then just use a database for unit testing as well.

Then you get a slow test suite. It's important to have a fast test suite to be able to do proper test driven development (which I still believe is the most efficient and effective way to write software, in general). Unit tests should be near 100% coverage. That means a lot of tests.

databases can run hundreds of test in a ms. Sure without you could get to thousands in that ms - who cares.

Re: Database mocks are not worth it

#193

Earlier quoted context omitted.

Any suggestions on where to read about this more?

https://www.destroyallsoftware.com/talks/boundaries

That's the only site whose dev contents I ever paid for. Gary Bernhardt is very entertaining.

Re: Database mocks are not worth it

#194

Earlier quoted context omitted.

The jargon around all this stuff is terrible. What I would probably write is, like, a fake version of that API, one which runs out of process from the library or test, and which can be "programmed" from the test set up -- "expect these requests, serve these responses", etc. Is that a mock? I don't know. It sure does resemble one, but it doesn't use dependency injection or other runtime tricks which I'd associate with…

Yes that still a mock. And thr point is to structure your code in such a way that there is little to no value left in testing that API call independently, because all of the related logic has been tested in a unit test. Once you've done that, you can just run a simple integration or end-to-end test to cover that API. You never need to manually mock it (like you suggested), or use a mocking tool.

> that still a mock

It's a fake, not a mock.

Mocks and fakes are both test doubles.

> And thr point is to structure your code in such a way that

Sometimes it's not your code. Sometimes you want to change legacy code and want tests to prove that your changes don't break anything.

Life would be so much easier if there were just one way to test, wouldn't it?

Re: Database mocks are not worth it

#195

Earlier quoted context omitted.

I am actually at a point in my career that I won’t work for a company that is dependent on stored procedures. Rollbacks, versioning, branching, testing and everything else is a pain once you introduce stored procedures. As a lead for mostly green field applications over the past decade, my one no compromise architectural edict is no stored procedures for online production code. I might use it for background utilities…

Is this about having application logic in multiple places, or having application logic co-located with the data? Does it make a difference if the procedures are database triggers vs being directly called by the application code? Would splitting off some of the logic into a separate service (that does its own database accesses) have the same issues?

Say I have functionality to get customer data. If the sql logic is in code, I can create a new branch and work on it, merge my changes, I can do blue/green deployments. A rollback if you’re using Kubernetes is a simple matter of reverting back to the configuration file containing a reference to the old Docker container etc.

How do you roll back a dozen stored procedures quickly? How do you just create a new branch or test a regression?

With all of the logic in code, it’s a simple matter of checking out a previous commit.

Triggers are even worse - “spooky actions at a distance”.

Re: Database mocks are not worth it

#196

Earlier quoted context omitted.

The jargon around all this stuff is terrible. What I would probably write is, like, a fake version of that API, one which runs out of process from the library or test, and which can be "programmed" from the test set up -- "expect these requests, serve these responses", etc. Is that a mock? I don't know. It sure does resemble one, but it doesn't use dependency injection or other runtime tricks which I'd associate with…

that is a fake. A mock is a device for verifying you called the expected funchtions. A fake emulates the api. Importantly if you change funcioms the fake will still pass if they mean the same - think of write which might take a buffer+length [C style], a list or a string (often there would be more than 10 variations)

i learned something new today, thanks

--

following in that theme, just doing some digging [1] turns up the following for those that might have been confused like i was:

  Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.

  Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).

  Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.

  Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.

  Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
[1] https://www.martinfowler.com/articles/mocksArentStubs.html

Re: Database mocks are not worth it

#198
post #3

I've found that replacing the database with in memory SQLite for tests is a sweet spot. Almost as fast as a mock, catches a lot of database issues. And it's really easy to do if you're using something like Django that makes automatically generating database migrations easy. It won't help you with database specific differences. But there should be very few of those if you're using a framework that abstracts away the d…

> But there should be very few of those if you're using a framework that abstracts away the database. But I really want that database-specific behaviour. :) PostgreSQL does so many amazing things (recursive CTEs, jsonb, etc) that actively make our system better. If there was a fork of Django that optimized for leveraging advanced postgres features, I'd use it.

SQLite does have recursive CTEs, but yeah, everything else that's all about types other than the ones SQLite supports...

Re: Database mocks are not worth it

#199
post #2

For tests, first use a real database. If you can't because the database just doesn't want to (ahem mongo ahem) then use a fake. If you can't use a fake, stop lying and use a fake. Mocks for databases are extremely brittle and complicated.

It's trivial to spin up a PG instance on an AF_LOCAL (Unix domain) socket, create the DB, populate it with schema and test data, then run your app's tests. If all the tests have different non-overlapping data then you can even share the one instance for all the tests.

Re: Database mocks are not worth it

#200
The one thing I greatly appreciate about Rspec (in RoR apps) is its ability to fully test the data layer. I maintain several such apps and database mocks are completely unnecessary, even going so far as to doing complete db setup and teardown between cases. Other apps I work on don’t really have this paradigm, so we resort to a combination of unit testing (JUnit) — which does involve significant mocking — and behavioral testing (Selenium) which of course indirectly tests database interaction. In the end, both methods accomplish the same goal of database testing but ideally you want “all of the above” to uncover edge cases, especially with critical infrastructure apps.
Post reply on HN