Events
- The best approach is to simply outsource your callback of your event into a own method that you can easily export it and write unit tests for this method.
- Then you only write 1x unit tests which makes sure that the correct callback function is called.
Stub Service Event with Event Emitter
- Stub the event in your service with an event emitter which you are emitting in your test. This is how you can trigger your callback in this case
getNewPairsEventHandler()
getNewPairsEventHandler()
in this case is a class method which can be easily stubbed or spyed with sinon if needed.
service.ts:
private getNewPairsEventHandler() {
return async(event: pairEvent) => {
//...
}
}
// Listen for new pairs
public async getNewPairs() {
const newPairsEvent = await this.uniswapPairCreatedFactory.events.PairCreated()
newPairsEvent.on('data', this.getNewPairsEventHandler())
newPairsEvent.on('error', (e: Error) => {
throw new BaseError('Error fetching new pairs', e)
})
}
test.ts:
describe('[SUCCESS]', () => {
let uniswapPairCreatedFactoryStub: sinon.SinonStub
let eventHandlerFn: any
let newPairsEvent: EventEmitter
let uniswapPairCreatedFactoryStub: sinon.SinonStub
const expectedEventArgs = {
returnValues: { token0, token1, pair }
}
beforeEach(() => {
eventHandlerFn = (<any>ethCoinManager.contract).getNewPairsEventHandler()
newPairsEvent = new EventEmitter()
uniswapPairCreatedFactoryStub = sinon.stub(
ethCoinManager.contract.uniswapPairCreatedFactory.events, 'PairCreated'
).resolves(newPairsEvent)
})
afterEach(() => {
uniswapPairCreatedFactoryStub.restore()
})
it.only('should listen for new pair events and save them to the database', async() => {
await getNewPairs()
await new Promise(resolve => {
newPairsEvent.once('data', () => {
resolve(true)
})
newPairsEvent.emit('data', expectedEventArgs)
})
expect(anythinghere)
})
})
Stub Service Event with Event Emitter and throw Error
- Same idea like above
Stub Service Event with Event Emitter
- However, in this example we will trigger the error Event. It is just a callback with a catch of the error and then pass it to a custom error logger.
service.ts
// Listen for new pairs
public async getNewPairs() {
const newPairsEvent = await this.uniswapPairCreatedFactory.events.PairCreated()
newPairsEvent.on('data', this.getNewPairsEventHandler())
newPairsEvent.on('error', (e: Error) => {
throw new BaseError('Error fetching new pairs', e)
})
}
test.js
describe('[newPairsEvent]', () => {
let newPairsEvent: EventEmitter
let uniswapPairCreatedFactoryStub: sinon.SinonStub
const errorMessage = 'Test error'
beforeEach(() => {
newPairsEvent = new EventEmitter()
uniswapPairCreatedFactoryStub = sinon.stub(
ethCoinManager.contract.uniswapPairCreatedFactory.events, 'PairCreated'
).resolves(newPairsEvent)
})
afterEach(() => {
uniswapPairCreatedFactoryStub.restore()
})
it('should throw an error if there is an error fetching new pairs', async() => {
await ethCoinManager.contract.getNewPairs()
try {
newPairsEvent.emit('error', new Error(errorMessage))
expect(true).toBe(false)
} catch (e: any) {
expect(e.name).toBe('BaseError')
expect(e.message).toBe('Error fetching new pairs')
expect(e.httpStatus).toBe(500)
expect(e.e.message).toBe(errorMessage)
}
})
})