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…
Database mocks are not worth it
81–90 of 268 posts
Re: Database mocks are not worth it
#82Two points: 1) The subtle issues with constraint violations, default values and indexes are part of the RDBMS, not the testing strategy. The article suggests stepping on these rakes in test so that you hopefully don't step on them in prod. Another way to avoid them in prod (and to also regain the speed/reliability/simplicity of your test suite) is to not use an RDBMS in prod. 2) If you want to persist something, ask…
> constraint violations You call these rakes and suggest removing them from prod, I call these vital safeguards. Defining constraints at the database layer gives me confidence that these will truly be invariants, and I won't one day discover that I've got millions of rows in my database missing critical data, with no way of knowing what should be there. Been there, done that, no desire to revisit it.
Re: Database mocks are not worth it
#83I've had some good experience with a mix of those approaches, maybe not using mocks per se, but an "in-memory database implementation" (just a wrapper around the hash map that implements the same behaviors as a repository that deals with a real database) on one hand, and testcontainers on the other. (Still, using an in-memory db is way better than mocking, the tests are not coupled to the implementation details/the u…
My take is that your business logic shouldn't know about your storage tech. (Like, dependency inversion 101 right?) > Still, using an in-memory db is way better than mocking, the tests are not coupled to the implementation details/the underlying model. Isn't this backwards? The fact that you've backed your storage with a HashMap (which is 100% what I shoot for too) means your service-under-test cannot know if it's ta…
EDIT: What I meant when I wrote that tests are not coupled to the underlying model/details is that with a mock you have to explicitly specify "when called with this return that". With an in memory database implementation you don't need to do anything, the code will just use the interface methods like "getX" or "saveY".
Re: Database mocks are not worth it
#84I 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…
I've had good experience with testcontainers ( https://testcontainers.com/ ) to do that sort of thing.
Re: Database mocks are not worth it
#85I'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…
Came here to say this: I’ve found that using SQLite for tests is a good sweet spot, and maintaining dual DB implementations ensures my business logic remains generic. But there is no replacement for running the tests agains the real database periodically (maybe only in CI for example). I wrote about this and some more in https://jmmv.dev/2023/07/unit-testing-a-web-service.html
Re: Database mocks are not worth it
#86I'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…
Does that cover the first two examples brought up by the article? Constraint violations and default value handling.
Re: Database mocks are not worth it
#87Sure, there's no substitute for optimizing things for a particular query engine and EVERY database engine has SUBSTANTIAL quirks (cough, cough Redshift), but you should be crawling and walking before you try running.
Re: Database mocks are not worth it
#88Earlier quoted context omitted.
This is a good thing to be aware of when choosing a database, but I think most of the time people just reach for Postgres because it's the "standard".
PostgreSQL stops many data bugs at the door due to being so strict -- something many programmers start rediscovering is a good thing by choosing stricter programming languages with time. I love SQLite to bits but the test harness I have to put around my apps with it is a separate project in itself.
Re: Database mocks are not worth it
#89Earlier quoted context omitted.
> 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 supports recursive CTE
I want to develop on postgres and test on postgres because I run postgres in production and I want to take advantage of all of its features. I don't understand why a person would 1) develop/test on a different database than production or 2) restrict one's self to the lowest common denominator of database features.
Test what you fly, fly what you test.
Re: Database mocks are not worth it
#90There's a continuum between extreme integration testing and extreme unit testing, each with their strengths and weaknesses.
There's a reason we don't do all testing through integration testing: it's slower, more flaky, and cripples developer velocity to a near standstill.
There's a reason we don't do all testing through pure unit testing: you have no idea whether the e2e plumbing works as expected.
DBs aren't special in this regard. That being said, it is true that investing in a light weight unit-testable setup for your DB is a good idea.