class UserRegistration {
async sendVerificationEmail (user) {
await Mail.send('emails.verify', user, (message) => {
message.to(user.email)
message.subject('Verify account')
})
}
}
You are viewing the legacy version of AdonisJS. Visit https://adonisjs.com for newer docs. This version will receive security patches until the end of 2021.
Quite often you want to fake out the original implementation of certain parts of your application when writing tests. Since AdonisJs leverages an IoC container to manage dependencies, it becomes so easy to create fake
implementations when writing tests
Let’s start with a basic example of faking out a service which sends an email to a given user.
Creating too many fakes in testing may lead to false tests, where all your are testing is the syntax and not the implementation.
Always make sure to keep fakes as the last option when writing tests. |
class UserRegistration {
async sendVerificationEmail (user) {
await Mail.send('emails.verify', user, (message) => {
message.to(user.email)
message.subject('Verify account')
})
}
}
Now let’s say this service is used by the UserController, when testing the user registration, a bunch of false emails is sent to some email address.
To avoid this behavior, it makes sense to fake out the UserRegistration
service.
const { ioc } = use('@adonisjs/fold')
const { test } = use('Test/Suite')('User registration')
test('register user', async () => {
ioc.fake('App/Services/UserRegistration', () => {
return {
sendVerificationEmail () {}
}
})
// code to test user registration
// ....
ioc.restore('App/Services/UserRegistration')
})
The ioc.fake
method let you bind a value to the IoC container, and when any part of the application tries to resolve the namespace, the fake value is return over the actual value.
In the same way, we need to call ioc.restore
to remove the fake.
This approach works great for a majority of use cases until you can create a fake which is similar to the actual implementation. For greater control, you can make use of external libraries like sinonjs.
AdonisJs mail provider comes with a fake, which can be used when writing tests.
const Mail = use('Mail')
const { test } = use('Test/Suite')('User registration')
test('register user', async ({ assert }) => {
Mail.fake()
// write your test
const recentEmail = Mail.pullRecent()
assert.equal(recentEmail.to.address, 'joe@example.com')
assert.equal(recentEmail.to.name, 'Joe')
Mail.restore()
})
Calling Mail.fake
method binds a fake to the IoC container. From this point, all emails are stored in memory as an array of objects, which can later be used for running assertions.
Below is the list of available methods on a fake mailer.
Returns the recent email object and removes it from the in-memory array.
Mail.pullRecent()
Just like Mail
provider, Event
provider also comes with an in-built faker object to store events inside an in-memory array and use them later for assertions.
const Event = use('Event')
const { test } = use('Test/Suite')('User registration')
test('register user', async ({ assert }) => {
Event.fake()
// write your test
....
const recentEvent = Event.pullRecent()
assert.equal(recentEvent.event, 'register:user')
Event.restore()
})
Alternatively, you can trap
an event inline and run assertions inside the callback.
test('register user', async ({ assert }) => {
assert.plan(2)
Event.fake()
Event.trap('register:user', function (data) {
assert.equal(data.username, 'joe')
assert.equal(data.email, 'joe@example.com')
})
// write your test
....
Event.restore()
})
Here is the list of all available methods
Returns the recent event object and removes it from the in-memory array.
Event.pullRecent()
A struggle to keep the database clean for each test is quite hard. You may end up using lifecycle hooks to truncate
the tables after each test.
To make this process easy, AdonisJs ships with a database transaction trait, which wraps all of your databases queries inside a transaction and roll it back after each test.
const { test, trait } = use('Test/Suite')('User registration')
trait('DatabaseTransactions')
That is all 😊