Let's write a test to make sure this Optimistic concurrency control stuff works as expected.
So here's the general idea.
Here's what we're gonna test.
We're going to first read an instance of a ticket we're going to save the ticket to the database we're
then going to fetch the ticket twice you're gonna fetch it two separate times three essentially have
two separate handles onto a ticket and they're both going to have some initial version flags set to
either 0 or 1 whatever the default is for the module that we just grabbed we're then going to make two
separate changes to the tickets we fetch.
When I say two separate I mean to say we're gonna make one change to the first ticket we fetch another
change to the second ticket we fetch we're then going to save the first batch ticket and we're going
to expect that that is going to work as expected because the first fetch ticket is going to have a version
number equal to what one or exactly greater than whatever the initial ticket that we save to the database
has its version number.
So we're going to expect that the first save is going to work as expected.
We're then going to try to save the second batch ticket when we try to save the second fetch ticket.
This thing is going to have an outdated version number because when we saved the first batch tickets
it will have incremented the version number inside of our database.
So when we tried to save the second one we're going to expect to see some kind of air something and
says hey you can't say this you've got some out-of-date version number or something similar to that
we're going to save the second patch ticket and expect an error.
That's the idea.
So let's get to it step number one create a ticket and save it.
They'll make a ticket using the ticket dot build method and I'll give this thing a title a price of
five.
And then we are required to provide a user I.D. as well.
I'll just give I.D. at 1 2 3.
Next up we're gonna say that your database will do in a way ticket save.
Now that ticket has been persisted into the database and in theory when we saved it Mongoose and more
specifically the update if current plugin should have assigned to some kind of version property to it.
So inside the database there's now a record that says Here is the ticket as a version of 0 or 1.
Again whatever the default version number is.
So now going to fetch that ticket out of the database twice so I'll do a first ticket.
But we call it first instance and that will be and a weight ticket that find by I.D. And we're going
to find a ticket dot I.D. then second instance a weight ticket that find by I.D. like so now we're going
to make a change to a first instance and to second instance will then save the first instance.
And that should work as expected.
Say the second one and we should see some kind of error.
So here's my change to both the tickets I'll say first instance I'll do a set and I'll update the price
to 10 you'll notice I'm once again getting it in error right here because when we do the fine by I.D.
we might get back no.
As usual I'm going to put an exclamation on there because again as usual we really want typescript to
just not worry about that.
If we fail to find that ticket I actually do want to see an error so we can fix up our tests then we'll
do our second instance exclamation.
We'll set our price to 15 Now here's the moment of truth.
We're going to attempt to save these first tickets so await first instance exclamation dot save and
that should go off as expected.
Now we'll put down our second save right here and this one when we run it should result in an error.
Right now we're going to throw the save in and we'll expect to see an error inside of our tests just
to make sure that the test is working as expected and that in general all the stuff is working as expected
around this versioning stuff.
So I'll do it a wait.
Second instance exclamation dot save.
And that's it let's say this I'm not going to go backwards my terminal and I have closed the tests suites
for my ticket service so I got to go into my tickets directory and do an NPM run test inside of here.
We're going to see a lot of different tests run because there's also doing all of our root handlers
and whatnot.
I do see the tests for my ticket stuff though.
OK it looks like I got one failure here.
I'm going to scroll up a little bit and there we go exactly what we wanted to see.
No matching document found for I.T..
Blah blah blah with the first number of 0 when we're trying to update Rice.
And you'll notice this error came from the second save.
So the second instance right here has an outdated version property has the incorrect version property.
Now even though this version property is outdated it's still kind of simulates what's gonna happen inside
of our actual application where we might eventually try to save a document with a version that's too
far into the future.
So this right here is excellent.
It means that this optimistic concurrency control stuff is working as expected.
Now we really just have to fix up the test and make sure that we somehow say that we expect that this
thing to go wrong.
Now just you know just does have some built in matches to help us expect that something is going to
throw an error.
It has a matter of expect some function to throw.
So we could do that in theory.
But I found that there are some Interop issues between just and typescript.
So I've found that this expectation right here does not quite work as expected if we wanted to really
do this we would do something like this like so.
But like I said I found that just doesn't work out too well with this.
If you're watching this at some point in the future perhaps you can see this actually work as expected.
But again I have not actually gotten this to work.
So instead we have to get just a little bit creative here so because we do expect this thing to throw
we're going to put in a try around that
we're going to put in a couch and we're going to expect to get into a catch and if we get into the catch
we're going to immediately return
and because we should be entering the couch right there right after the throw a air manually.
So throw new air and I'll say should not reach this point.
So if our test is working as expected when we run this line of code right here we're going to throw
an error that's going to cause us to enter the catch statement we should return automatically and when
we return we will not get to that error.
If this line of code does not throw then we're going to skip over the catch and we're going to get the
error that's going to throw the air and that's going to cause our test to fail.
Now one other little gotcha if you're going to use this pattern right here just cannot really figure
out the async await situation here I can't really figure out when our tests are all done.
When we call return right here.
So you just help types you me to help just out.
We have to receive a callback to our actual test function right here of done done is a function that
we should invoke manually if we want to specifically tell just that we are done with our test and that
should not expect anything else to go on with our test so right when we return right here we're gonna
also called Don and just very officially tell just.
That's it.
Test complete.
Don't worry about anything else inside this test.
So again all this stuff right here is just to work around the fact that right now just with that to
throw matter doesn't quite work as expected.
OK.
So let's say this and see how we're doing.
Flip back over
and it looks like everything is passing now.
Let's run just our ticket test file by itself just to save ourselves a little bit of time here so I
can hit W to enter the watch menu then P to enter in the name of the file I want to run and we want
to run the ticket test file.
So let's put in a better ticket.
Oh they all say ticket inside of it I guess I guess I have to use a bit more.
Oh yeah.
I have to use all bit more specific button that lets do ticket dot test that's better.
Now we're just running that one test.
Very good.
And as usual let's try to make it fail just one time here so I'll try commenting out the oh wait it's
like an instance save.
I'll say the file.
And there we go.
Looks like if it doesn't throw an error we do in fact end up getting to that error at the bottom and
the tests fail.
ALEX Good.
So this is pretty fantastic stuff.
This means that we can now be really sure that when we save a record if we save it successfully we are
saving it essentially in the correct order and we're not working on some kind of stale data.
And in the instance of our order service more processing events this is also going to make sure that
we are processing events in the correct order.
There is one other very quick test I would like to write in the next video so quick pause right here.
I'll see you in just a minute.