DT
Drizzle Team•2y ago
petja

Mocking database

I want to mock the PostgreSQL database and access it with Drizzle ORM. I tried to write a TypeScript class that should work the same way as pg's Pool class, but instead of hitting an actual database, returns rows from an in-memory object. However when SELECT'ing from the table I had mocked, Drizzle returned an object with all keys having undefined values. Any help? 🙂
export class MockPool {
private mocks: Record<string, (params: any[]) => Record<string, any>[]> = {};

mockQuery(query: string, rows: (params: any[]) => Record<string, any>[]) {
this.mocks[query] = rows;
}

async query(
query: string | QueryConfig,
values?: any[]
): Promise<Partial<QueryResult>> {
let queryConfig: QueryConfig;

if (typeof query === "string") {
queryConfig = { text: query, values };
} else {
queryConfig = { ...query };

if (values) {
queryConfig.values = values;
}
}

const mock = this.mocks[queryConfig.text];

if (!mock) {
throw new Error(`Missing mock for query ${queryConfig.text}`);
}

const rows = mock(queryConfig.values ?? []);

return {
rowCount: rows.length,
rows,
};
}
}
export class MockPool {
private mocks: Record<string, (params: any[]) => Record<string, any>[]> = {};

mockQuery(query: string, rows: (params: any[]) => Record<string, any>[]) {
this.mocks[query] = rows;
}

async query(
query: string | QueryConfig,
values?: any[]
): Promise<Partial<QueryResult>> {
let queryConfig: QueryConfig;

if (typeof query === "string") {
queryConfig = { text: query, values };
} else {
queryConfig = { ...query };

if (values) {
queryConfig.values = values;
}
}

const mock = this.mocks[queryConfig.text];

if (!mock) {
throw new Error(`Missing mock for query ${queryConfig.text}`);
}

const rows = mock(queryConfig.values ?? []);

return {
rowCount: rows.length,
rows,
};
}
}
Using the mock pool:
import { drizzle } from "drizzle-orm/node-postgres";
const pool = new MockPool()
const db = drizzle(pool as any) // any, because we're not implementing whole Pool class

pool.mock('SELECT * FROM users', () => [{ id: '1234', name: 'Petja' }])

usersTable.select() // { id: undefined, name: undefined }
import { drizzle } from "drizzle-orm/node-postgres";
const pool = new MockPool()
const db = drizzle(pool as any) // any, because we're not implementing whole Pool class

pool.mock('SELECT * FROM users', () => [{ id: '1234', name: 'Petja' }])

usersTable.select() // { id: undefined, name: undefined }
7 Replies
Dan
Dan•2y ago
we're querying the DB using raw mode, which returns a row as a tuple of values, not as an object. Also, we don't do * selects because of that. You can enable logging on the Drizzle instance and see the exact queries that it sends.
petja
petjaOP•2y ago
Yeah, the code above was just an example out of my head. My code throws an error and the query Drizzle made if there's no matching mock. I'm not sure what should I change to work with this raw mode. Can you enlighten me a bit?
Dan
Dan•2y ago
It's called an "array" mode in node-pg
petja
petjaOP•2y ago
Thanks, got it working now 🙂 Any plans to bring mocking into Drizzle level some day? I think it would be helpful for many devs.
Dan
Dan•2y ago
Funny thing - we had it at some point, but then decided to remove Drizzle doesn't manage the DB connection, so I don't think it makes sense to mock inside of Drizzle, since it works with a lot of different drivers
johnnydt
johnnydt•2y ago
@Petja Touru would you mind sharing your solution that fixed this?
Want results from more Discord servers?
Add your server