Stubbing leveldb calls for testing
There are three approaches I'm using right now
Testing for the batch
operation
The great thing about this, is that you don't need to mock the leveldb module out, but just testing the you modules returns a list of operations:
const ops = [
{type: 'put', key: 'shorts', value: 'pants'},
// etc
]
You just need to test that the array returned by your test subject contains what you need (using Jest here):
test('list the notebooks', () => {
let result = subject(simpleCase)
let putCommand = R.find(
R.propEq('key', 'tags:tag001:nbook001:note001'),
result
)
expect(putCommand).toMatchObject({
type: 'put'
})
})
You can also stub out the batch
method and test how it was called
const batch = jest.fn()
batch.mockReturnValue(Promise.resolve('inserted'))
const db = { get, batch, del }
jest.mock('./utils/db')
const getDb = require('./utils/db')
getDb.mockReturnValue(db)
// ... later
test('inserts the note', () => {
expect(batch.mock.calls[0][0]).toContainEqual({
type: 'put',
key: 'noteid',
value: {
nbook: { name: 'nbookname' },
note: { meta: { title: 'notetitle' } }
}
})
})
Stubbing the get
method
The get
and put
methods are easier to stub out, because they are just asynchronous function calls or promises
const get = jest.fn()
get.mockImplementation(r => {
return new Promise((res, rej) => {
if (r === 'nobook:new_nbookid') {
rej('not found')
} else {
res({ updated_at: '101' })
}
})
})
const db = { get, batch, del }
jest.mock('./utils/db')
const getDb = require('./utils/db')
getDb.mockReturnValue(db)
Using memdown
for more complex scenarios, e.g. stubbing createKeyStream
I've been experimenting with creating my own Readable stream provider and using it for stubbing methods like createReadStream
.
from2 is a great package for doing this, but finally I realised that I should not go that far.
Instead, you can just use memdown for a temporary leveldb store.
const db = levelup(encode(memdown()))
const data = [
{ type: 'put', key: 'tags:atag1', value: 'pants' },
{ type: 'put', key: 'tags:atag2', value: 'pants' },
]
db.batch(data, err => {
if (err) {
console.log('Ooops!', err)
}
})
jest.mock('./utils/db')
const getDb = require('./utils/db')
getDb.mockReturnValue(db)
To make sure it mirrors the encoding used by the "real" leveldb store, you have to pass the memdown store into encoding-down