In the jest docs it mentions an example in the async tutorial
// Or try-catch.
it('tests error with async/await', async () => {
try {
await user.getUserName(2);
} catch (object) {
expect(object.error).toEqual('User with 2 not found.');
}
});
I think that this code should be written like this:
// Or try-catch.
it('tests error with async/await', async () => {
try {
await user.getUserName(2);
fail();
} catch (object) {
expect(object.error).toEqual('User with 2 not found.');
}
});
The fail()
will prevent the test from passing if getUserName()
does not throw an error.
However, I see no mention of the fail()
command anywhere in the docs, is this a supported API?
I'm not sure if we want to have a function like this.
fail()
as you proposed here will also prevent the test from passing if getUserName()
doesn't throw and returns instantly.
Instead you could test if getUserName
function throws with e.g. .toThrow()
method: http://facebook.github.io/jest/docs/api.html#tothrow
How would you use toThrow() to check for a rejection of a promise? Isn't toThrow only used to check if errors are thrown in a particular function?
If you want to test Promise rejection, you can still go on with something like this:
it('tests if getUserName rejects promise', () => {
user.getUserName(2)
.then(() => {}, error => {
expect(error).toBe('My rejected Promise')
})
});
There are plenty of ways, I just don't see the reason to add another one.
The problem with your method is that if the promise resolves then the test will pass even though you expect it to reject.
The test should fail if the promise resolves. It should only pass if it rejects with the exact error that you expected.
it('tests error with async/await', async () => {
try {
await user.getUserName(2); //If this resolves then the test will pass
} catch (object) {
expect(object.error).toEqual('User with 2 not found.');
}
});
I'm not sure if it's possible to do with async/await syntax, I didn't play with it much to be honest.
But maybe we could introduce a new matcher e.g. .toBeRejected(object | string)
?
Then you could test the case like this:
it('rejects on username 2', () => {
const object = {error: 'User with 2 not found'};
expect(user.getUserName(2)).toBeRejected(object);
})
Yeah such an API would be awesome! And you could also use snapshots here:
it('rejects on username 2', () => {
expect(user.getUserName(2)).toBeRejectedWithSnapshot();
Closing this in favour of #1377. You're welcome do discuss new this API shape there.
Somehow this is not documented, but since Jest uses Jasmin this is possible:
test('How to manually fail tests', done => {
done.fail(new Error('I want my test to fail'))
})
You can also call done.fail()
after done()
has been called. This is important if you want to fail conditionally when a specific thing happens.
For example I wanted any call to console.error
to trigger an exception and fail the test in question:
// console.error should fail the test
beforeEach(done => {
jest.spyOn(global.console, 'error').mockImplementation(e => {
done.fail(e);
});
done(); // it is important to call this here or every test will timeout
});
The above did not work for me. But managed to make it work using this,
test("handleResponse - reject", () => {
return expect(
new Promise((resolve, reject) =>
myFile.myMethod(input, resolve, reject)
)
).rejects.toEqual("promise rejection tested");
});
In case anyone else comes across this, the global function fail
works. I believe it's a feature of Jasmine.
it('should not fail', () => {
try {
myFunctionThatWillNotError()
} catch (e) {
fail('should not have thrown an error')
}
})
This is the idiomatic example from the docs:
test('the fetch fails with an error', async () => {
expect.assertions(1);
try {
await fetchData();
} catch (e) {
expect(e).toMatch('error');
}
});
This feature is also useful in case you are programmatically generating test
/it
blocks based on async code. For example reading a text file -avoiding readSync- to assert something for each line.
As the describe
doesn't allow the callback to return a promise (#2235), you cannot generate many its
. So the solution is to use a beforeAll
for the async code. Then you can only have a single it/test
for the whole file.
So, if an expect fails, the error won't be verbose enough to understand the error (which line failed)
It is then cool to have a way to make it fail with a custom message.
Here is my example. done.fail()
worked but an out-of-the-box fail()
would get rid of the done()
.
Also having a custom message for expect()
could have done it.
describe('examples from file', () => {
let lines;
beforeAll(() => new Promise(resolve => {
lines = []
// asynchronously read each line into lines
}))
it('should accept all lines in samples.txt', done => {
lines.forEach(line => {
if (!someBooleanChecking(line)) {
done.fail(new Error(`"${line}" was NOT accepted !`))
} else {
done()
}
})
})
})
This is the idiomatic example from the docs:
test('the fetch fails with an error', async () => { expect.assertions(1); try { await fetchData(); } catch (e) { expect(e).toMatch('error'); } });
Won't this pass if fetchData() doesn't throw as the test is expecting?
Therefore is something like this required?
test('the fetch fails with an error', async done => {
expect.assertions(1);
try {
await fetchData();
} catch (e) {
expect(e).toMatch('error');
done();
return;
}
done.fail('expected promise rejection did not occur as expected');
});
Won't this pass if fetchData() doesn't throw as the test is expecting?
No, expect.assertions(1);
will fail the test if no assertion is run
In case anyone else comes across this, the global function fail works. I believe it's a feature of Jasmine.
That will stop working at some point - it's not part of Jest's documented API.
Also, any reason why you aren't using this?
test('the fetch fails with an error', async () => {
expect.assertions(1);
await expect(fetchData()).rejects.toMatch('error');
});
I totally missed the expect.assertions(1) line. nice
So related to this, I'm currently trying to force my Jest tests to fail if console.error
or console.warn
is called. Unfortunately, the only reliable way I've found to do so is to use fail()
:
```const error = console.error;
console.error = function(message) {
error.apply(console, arguments); // keep default behaviour
fail(message);
};
const warn = console.warn;
console.warn = function(message) {
warn.apply(console, arguments); // keep default behaviour
fail(message);
};
```
Raising an error does not work reliably when dealing with asynchronous React code, unfortunately. Does anyone have any thoughts on how this could be made to work without resort to fail()
?
It does look like using expect.assertions(Infinity)
works, but that certainly seems like an abuse of the intent of expect.assertions
.
When we use it with restartBrowserBetweenTests:true -done.fail(msg) causing no such session error to the rest of the test cases when we perform it in chrome
Most helpful comment
Somehow this is not documented, but since Jest uses Jasmin this is possible: