Writing tests for your RxDB application is crucial to ensure reliability. Because RxDB runs in many different environments (Browser, Node.js, React Native, Electron, …), testing strategies might vary. However, there are some common patterns that make testing easier and faster.
Writing tests for your RxDB application is crucial to ensure reliability. Because RxDB runs in many different environments (Browser, Node.js, React Native, Electron, …), testing strategies might vary. However, there are some common patterns that make testing easier and faster.
memory RxStorageFor unit tests, you should generally use the memory RxStorage. It keeps data only in memory, which has several advantages:
import { createRxDatabase } from 'rxdb';
import { getRxStorageMemory } from 'rxdb/plugins/storage-memory';
const db = await createRxDatabase({
name: 'test-db',
storage: getRxStorageMemory()
});
using KeywordRxDB supports the Explicit Resource Management using keyword (available in TypeScript 5.2+). This automatically closes the database when the variable goes out of scope, which is perfect for tests.
Instead of manually calling await db.close(), you can do:
describe('my test suite', () => {
it('should insert a document', async () => {
// Did you know?
// using 'using' ensures db.close() is called automatically
// at the end of the test function.
await using db = await createRxDatabase({
name: 'test-db',
storage: getRxStorageMemory()
});
await db.addCollections({ ... });
// ... run your tests
});
});
When running many tests, it is important to ensure that all databases are cleaned up after your tests run. Having non-closed RxDatabase instances after some tests can significantly decrease performance because background tasks and event listeners are still active.
A good practice is to verify that no database instances or connections are left open. You can check internal RxDB states to ensure everything is closed.
import { dbCount } from 'rxdb/plugins/core';
import assert from 'assert';
describe('cleanup', () => {
it('ensure every db is cleaned up', () => {
assert.strictEqual(dbCount(), 0);
});
});
To test multi-tab behavior (like Leader Election or Replication) within a single Node.js process or test runner, you can create multiple RxDatabase instances with the same name and storage. RxDB will treat them as if they were running in different tabs or processes. Notice that for this, ignoreDuplicate must be set to true because otherwise it will not allow to create multiple databases with the same name in a single JavaScript process.
import { createRxDatabase } from 'rxdb';
import { getRxStorageMemory } from 'rxdb/plugins/storage-memory';
// Simulate Tab 1
const db1 = await createRxDatabase({
name: 'test-db', // same name
storage: getRxStorageMemory(),
ignoreDuplicate: true // must be set to true
});
await db1.addCollections({ ... });
// Simulate Tab 2
const db2 = await createRxDatabase({
name: 'test-db', // same name
storage: getRxStorageMemory(),
ignoreDuplicate: true // must be set to true
});
await db2.addCollections({ ... });
// insert at "tab one"
await db1.todos.insert({ id: "foobar"});
// read at "tab two"
const doc = await db2.todos.findOne("foobar").exec(true);
assert.ok(doc);
This works because the memory storage (and others) are shared within the same JavaScript process.