Live data from Hacker News

Database mocks are not worth it

shayon.dev

181–190 of 268 posts

Re: Database mocks are not worth it

#181

Earlier quoted context omitted.

how do you test the imperative shell except with mocks? Suppose you're calling an external API

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)

Re: Database mocks are not worth it

#182
post #66
post #42

Testing against a real database is an example of integration testing. Using mocks is for unit testing. Ideally, you want to do both. Unit testing entails isolating particular components for testing which is important because it let's you be more precise in what exactly you're testing. Using mocks also makes it easier to run automated tests because it means you don't need to have a database or credentials handy during…

Then just use a database for unit testing as well.

Because then you wouldn't be doing unit testing; you'd be doing integration testing. You'd also probably not be testing the database in a realistic configuration and thereby missing the whole point.

Re: Database mocks are not worth it

#183

Don’t code with mocks period. Structure your code such that it has a functional core and imperative shell. All logic is unit testable (functional core). All IO and mutation Is not unit testable (imperative shell). Mocks come from a place where logic is heavily intertwined with IO. It means your code is so coupled that you can’t test logic without touching IO. IO should be a dumb layer as much as possible. It should b…

This throws away most of what your database can do for you. I personally like to do authorization at the database layer. There are a tons of other things a DB can do, like trigger a webhook. Are you going to frequently pull from your DB for live updates?

I think OP issue is that he didn't understand what mock tests actually tested against. They are called mock for a reason. There should be a better way to provision a database when running tests and have a full simulated environment.

Re: Database mocks are not worth it

#184
post #5

I thought this was common knowledge and that it became even easier after Docker became a thing? Mocks are wishful thinking incarnate most of the time, though here and there they are absolutely needed (like 3rd party APIs without sandbox environments, or quite expensive API, or most of the time: both). Just pick a task runner -- I use just[0] -- and make a task that brings up both Docker and your containers, then run…

Too many people use fakes and call them mocks. Which makes the conversations quite tortured.

I've beconeea fan of good fakes. Good fakes closely resemble the real service but let me query useful things in tests. Mocks just tell me I called a function without concern for the 10 different ways to doethe thing.

Re: Database mocks are not worth it

#185

Don’t code with mocks period. Structure your code such that it has a functional core and imperative shell. All logic is unit testable (functional core). All IO and mutation Is not unit testable (imperative shell). Mocks come from a place where logic is heavily intertwined with IO. It means your code is so coupled that you can’t test logic without touching IO. IO should be a dumb layer as much as possible. It should b…

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?

Re: Database mocks are not worth it

#186

My #1 rule: tests should "just work". A new contributor should not have to run any setup, just a single test command. I don't care what kind of tests they are or what you prefer to call them as long as they work (in CI AND locally). The vast majority of projects fail at this, often because some external dependency like a database than needs some manual set up. To me, mocking out the db is a relatively cheap way to ac…

I agree on the "just work" principle, but stuff like "docker compose" is easy enough to use, and "standard enough". Typing "docker compose up -d" once isn't that much effort. And make sure the connection string is configurable through an environment variable so people can use $something_else if they really want/need to.

Practicality beats purity, and all of that. Especially when it saves quite of complexity in the code itself – new contributors are going to struggle with that, too.

In short, the setup doesn't need to be manual.

Re: Database mocks are not worth it

#188
post #121

Earlier quoted context omitted.

> If it gets changed to also return "bar", and you forget to update the mock, you've got a time-bomb in your code. In that case the problem isn't so much that you forgot to update your mock as much as the changed function no longer satisfies the interface. Ensuring that an implementation properly satisfies the interface is not within the scope of tests where mocking would be useful.

> Ensuring that an implementation properly satisfies the interface is not within the scope of tests where mocking would be useful. As I mentioned, if you need mocks to test a code path, you are probably "doing it wrong" as there are much better ways to do that. Such as refactoring the code so you can test just that code path. Mocks are a code smell, IMHO. In other words, if you need mocks, then the interface/contract…

> if you need mocks to test a code path, you are probably "doing it wrong" as there are much better ways to do that.

Most code paths you want to test are error branches, and creating real error conditions is hard to completely unrealistic (e.g. causing hardware malfunction on each test run). What is the better way in your mind?

Mocks can only exist at the integration points, fundamentally. There is a natural interface there, an interface that you are not supposed to be testing. Those tests already exist around the module that provides the integration. You don't need to test it again.

If a mock standing in for the real thing causes ill-effects, you've done something wrong. You're not supposed to be testing the mock while using the mock. If your mocks need tests (they probably do!), they should be tested outside its use.

Re: Database mocks are not worth it

#189

Earlier quoted context omitted.

Does something like PGlite work for your use case? https://pglite.dev/

You can just simply run postgres, why bother with pglite? postgres installs easily on WSL2 or whatever Linux distribution you're using.

Agreed. Running docker-compose and postgres-alpine works just fine.

Re: Database mocks are not worth it

#190

Earlier quoted context omitted.

I've had a nice experience using Docker Compose for this, although you might still want a task runner wrapper around it. Podman Compose should work fine as well.

My current setup on a personal project is docker compose with Postgres and pgadmin container. I would never think of mocking a database in 2024/2025, just spin one up. Also keep your lynch pin invariants in the database and not in your code.

in 2024/2025 you just might be working with 985 petabyte database which just might have a few issues being “spun up” :)
Post reply on HN