I am trying to stub the following:
on('complete', function(data){ });
I only want to call the callback if the first parameter is 'complete'.
The function I am testing also contains:
on('error', function(data){ });
So I can't just do yield cause that will fire both the complete and the error callback.
If I wouldn't use sinon I would fake it by writing the following.
var on = function(event, callback){
if (event === 'complete'){
callback('foobar');
};
};
I am trying to stub the following:
on('complete', function(data){ });
I only want to call the callback if the first parameter is 'complete'.
The function I am testing also contains:
on('error', function(data){ });
So I can't just do yield cause that will fire both the complete and the error callback.
If I wouldn't use sinon I would fake it by writing the following.
var on = function(event, callback){
if (event === 'complete'){
callback('foobar');
};
};
Share
Improve this question
asked May 14, 2012 at 17:23
PickelsPickels
34.6k26 gold badges120 silver badges181 bronze badges
1
- 2 Can you show a more full example of the function containing this? – Oved D Commented Dec 11, 2012 at 21:37
3 Answers
Reset to default 9You can narrow the circumstances under which a yield
occurs by combining it with a withArgs
like so...
on.withArgs('complete').yields(valueToPassToCompleteCallback);
on.withArgs('error').yields(valueToPassToErrorCallback);
Maybe you can use a spyCall:
var spy = sinon.spy(window, 'on');
on('error', function(data){ });
on('complete', function(data){ });
for(var i=0; i < spy.callCount; i++){
var call = spy.getCall(i);
if(call.args[0] === 'complete') call.args[1]('foobar');
}
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)
}
})
})