Closed patrickhousley closed 6 years ago
I have been playing with testing an event handler and below is what I have so far.
import { Test } from '@nestjs/testing';
import { EventBus } from '@nestjs/cqrs';
import { rand } from '@buffalo/common/src/test-lib/random';
import { SendEmailHandler } from './send-email.handler';
import { EmailService } from '../../email.service';
import { SendEmailEvent } from '../impl/send-email.event';
import { MessageTransmissionMethod } from '../../../queue/queue.interface';
import { ProcessedEvent } from '../../../queue/events/impl/processed.event';
// Disable log outputs
jest.mock('@nestjs/common/services/logger.service');
describe('UNIT: SendEmailHandler', () => {
let eventBus$: EventBus;
let emailService: EmailService;
let sendEmailHandler: SendEmailHandler;
beforeEach(async () => {
const module = await Test.createTestingModule({
components: [
SendEmailHandler,
{
provide: EventBus,
useFactory: () => jest.fn()
},
{
provide: EmailService,
useFactory: () => jest.fn()
}
]
}).compile();
eventBus$ = module.get<EventBus>(
EventBus
);
emailService = module.get<EmailService>(EmailService);
sendEmailHandler = module.get<SendEmailHandler>(SendEmailHandler);
});
it('should be defined', () => {
expect(eventBus$).toBeDefined();
expect(emailService).toBeDefined();
expect(sendEmailHandler).toBeDefined();
});
it('should send the email using the EmailService', async () => {
emailService.sendEmail = jest.fn(() => Promise.resolve());
eventBus$.publish = jest.fn(() => { /* Do Nothing */ })
await sendEmailHandler.handle(
new SendEmailEvent(
{
MessageId: rand.n(rand.letter, 10).join('')
},
rand.n(rand.letter, 10).join(''),
rand.n(rand.letter, 10).join(''),
rand.n(rand.letter, 10).join(''),
{},
MessageTransmissionMethod.EMAIL
)
);
expect(emailService.sendEmail).toHaveBeenCalledTimes(1);
});
it('should publish a new ProcessedEvent to the event bus', async () => {
const event = new SendEmailEvent(
{
MessageId: rand.n(rand.letter, 10).join('')
},
rand.n(rand.letter, 10).join(''),
rand.n(rand.letter, 10).join(''),
rand.n(rand.letter, 10).join(''),
{},
MessageTransmissionMethod.EMAIL
);
emailService.sendEmail = jest.fn(() => Promise.resolve());
eventBus$.publish = jest.fn(() => { /* Do Nothing */ });
await sendEmailHandler.handle(event);
expect(emailService.sendEmail).toHaveBeenCalledTimes(1);
expect(eventBus$.publish).toHaveBeenCalledTimes(1);
expect(eventBus$.publish).toHaveBeenCalledWith(
new ProcessedEvent(
event.sqsMessage,
event.app,
event.recepient,
event.template,
event.templateData,
event.transmissionMethod
)
);
});
it('should not publish a new ProcessedEvent to the event bus if sending the email fails', async () => {
emailService.sendEmail = jest.fn(() => Promise.reject(new Error('Test Error')));
eventBus$.publish = jest.fn(() => { /* Do Nothing */ });
await sendEmailHandler.handle(
new SendEmailEvent(
{
MessageId: rand.n(rand.letter, 10).join('')
},
rand.n(rand.letter, 10).join(''),
rand.n(rand.letter, 10).join(''),
rand.n(rand.letter, 10).join(''),
{},
MessageTransmissionMethod.EMAIL
)
);
expect(emailService.sendEmail).toHaveBeenCalledTimes(1);
expect(eventBus$.publish).toHaveBeenCalledTimes(0);
});
});
I am having a harder time getting the E2E testing. When I add the CQRSModule to the testing module, Nest can't resolve dependencies of the EmailService (?, +, +, +). Please verify whether [0] argument is available in the current context.
That first dependency is EventBus
.
After some sleep, finally figured out what I was doing wrong. Although the error was a little misleading, I figured out that I forgot to override all the components of the modules my EmailModule
imported.
const module = await Test.createTestingModule({
modules: [EmailModule]
})
// CQRSModule Overrides
.overrideComponent(EventBus)
.useValue({
setModuleRef: jest.fn(),
register: jest.fn(),
publish: jest.fn()
})
// SharedModule Overrides
.overrideComponent(constants.EMAIL_SOURCE_ADDRESS)
.useValue(rand.n(rand.letter, 10).join(''))
.overrideComponent(constants.EMAIL_REPLY_ADDRESS)
.useValue(rand.n(rand.letter, 10).join(''))
// TemplateModule Overrides
.overrideComponent(constants.AWS_S3_SERVICE)
.useValue(jest.fn())
.overrideComponent(TemplateService)
.useValue(jest.fn())
// EmailModule Overrides
.overrideComponent(constants.AWS_SES_SERVICE)
.useValue(jest.fn())
.compile();
Closing since I got this figured out.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
I'm submitting a...
Current behavior
No documentation exists around unit or e2e testing the cqrs module.
Expected behavior
Please provide some examples for the various patterns supported by the cqrs module.
Minimal reproduction of the problem with instructions
N/A
What is the motivation / use case for changing the behavior?
Make the documentation as good as the library is.
Environment