- In this section, we're going to see how to test Promises.
The previous section introduced Promises
and how they work, resolving and rejecting.
And we saw a function that looks
like this in the TestingPromises folder for lesson four.
We saw a function called doTask
where we passed in a task number
like one, two, three, four, five
and a random number between zero and one
and the function between the Promise.
The Promise had some code in here
which ran a long running task in this function here.
We had a timeout which was kind of a randomized time.
After that timeout occurred,
the random number depended
on whether it was greater than or less than 0.5.
We either called the resolve call
back on the Promise to say yes, it worked,
and here's the result.
Or if the random number was too big, greater than 0.5
we tell the Promise that it rejected
with an error message here.
Okay?
So that's the code in task.js in the demo folder.
Here it is.
If you wanna have a look for yourself,
that's the doTask function I just showed.
And what we're gonna do now is see how to test it.
How can we test that it returns,
that it resolves when it should
and it rejects when it should.
Okay. So this is one way to do it.
First of all, how can you check that a Promise resolves?
This is what you do.
I've got a test function here.
It tests that the task resolves
if the random number was less than 0.5.
Okay, so note these points.
Well first of all, what you do is you call the function
that you're trying to test.
Okay?
So that, I call the function
with a small number, less than 0.5.
Ideally, if that function is working correctly
it should resolve.
It returns a Promise and that Promise should resolve.
Okay, so I take that Promise object that it returns,
and upon that Promise object, I call then.
So this should happen.
The Promise, if it's working correctly
this function should return a Promise that resolves
and it should pass me the result.
And I passed in a value one here,
so it should, the result should be,
and this is where you put your expect.
The result should be Task 1 resolved.
That was the task number.
This is the string I'm expecting to get back.
Okay?
So you call the function, which returns a Promise.
You assert the result of that Promise.
And then you return that Promise object back to Jest.
Jest waits for that Promise object to finish
before it moves on beyond the test.
Okay, so you have to return this Promise object here.
You have to return back to Jest
so that Jest knows to wait for that Promise object
to finish before it can go on to the next test
so it doesn't kind of terminate prematurely.
So that's how to test if my Promise object was resolved.
Similar kind of idea to test
if it rejects.
In this case here I'm testing that my task,
the function that I'm calling,
tells the Promise that it rejects
if the value is 0.5 or higher.
Okay, now then there is a slight complication here
which I'll get back to in a moment.
The first thing you have to do
is you have to specify how many assertions do you expect
to happen in this test?
What this statement does,
we haven't seen it before,
I'm telling Jest I expect one assertion,
one expect call, in other words, to happen in my test.
Okay?
So one expect test must happen when this test...
Not this expect, but this expect.
I'm making sure that at least one assertion happens
when this test is executed.
Bear that thought in mind for a moment.
Okay, what I then do is similar to before.
I call my function into test, giving it some sample values,
Task 1, a value that should cause rejection.
Okay?
So, you know, if my function is written correctly,
it should resolve, it should reject the Promise.
And I catch that problem in my catch function here.
Okay?
And then don't forget to return the result
of this promise back to Jest.
Now the reason why you need expect.assertions here
is to guard against a false positive.
Imagine that there was a bug in my code,
and I was hoping that my code would reject
but because of a bug, this code actually resolves.
Okay?
So if that task inadvertently resolved
then this code would never be executed.
And therefore it wouldn't actually get to my expect clause.
So I'd get a false positive there.
I wouldn't get any problems here.
It would never get into my catch handler
because the task didn't reject.
So this expect.assertions is a guard
against a false positive.
If there was a bug in my function here
and it resolved when it should reject,
this function would return immediately,
but Jest would give me an error
because it didn't run through this expect clause
because it resolved, not rejected.
It didn't get into here.
It never ran that code.
Therefore, we didn't get one assertion
and it would fail because of that reason.
Okay?
So that's the guard against,
or to check that the Promise didn't accidentally resolve
when it should have rejected.
You do need that there to make sure
that this statement was actually executed.
And don't forget to return the Promise object
back at the end of your test as well.
So to run that test, to run those two tests,
you could do it like this.
- t test promises using then/catch.
Okay?
That will take for both of those tests
that I just showed you.
If you run that test command from the test folder
then it'll run this function here.
Task resolves if value < 0.5.
And task rejects if value > 0.5.
This string here,
test promises using then/catch,
and my task suite
that's the suite here that contains those two tests,
testing that it rejected, so resolved and rejected
when it should have done.
That's that first suite there.
Now as it happens,
there is another way to test Promises.
There is a resolves matcher and rejects matcher.
So this is, you might prefer this
as an alternative, easier way
to check if a Promise has succeeded or failed.
So here, what you do is you call the expect function
and you give it the function
that you are operating on.
So this function here should return a Promise.
Okay?
So you say I'm expecting that this Promise resolves
and I'm expecting the result to be Task 1 resolved.
Likewise, and then you return this construct.
Okay?
Because basically it's gonna return a Promise
back to Jest.
Alternatively, you can say right call that function,
that returns a Promise.
I'm expecting that return value, that Promise,
to reject and I'm expecting the error message to be
Task 1 rejected.
So the resolves matcher
and the rejects matcher is a cleaner alternative
to what we just showed you
as a way of dealing with Promises
that may succeed or may fail.
So if you run that bunch of tests,
those tests are in this suite here,
test promises using resolves/rejects matchers.
So it uses the resolves matcher
and the rejects matcher.
Call the function returns a Promise.
Expect that returned Promise to resolve
with that value.
Call the function returns a Promise.
Expect that Promise to reject with that error message.
Okay?
So when I run this test suite, my code is correct
so my test suite should succeed and there you go.