Check out a free preview of the full API Design in Node.js (using Express & Mongo) course:
The "Exercise 5" Lesson is part of the full, API Design in Node.js (using Express & Mongo) course featured in this preview video. Here's what you'd learn in this lesson:

In this exercise, you will write tests for all the CRUD routes in the application. You will use Mocha to run the tests and view the results.

Get Unlimited Access Now

Transcript from the "Exercise 5" Lesson

[00:00:00]
>> [MUSIC]

[00:00:03]
>> Speaker 1: So now, if you go into step five, you're going to notice some small differences here than where we left off yesterday. The first thing you notice is there is this new file, index.js, does anybody know the meaning of index.js inside of node? Do you know? That's awesome.

[00:00:26] Anybody else know?
>> Speaker 2: Is that a convention or-
>> Speaker 1: It's a convention, and it also has an actual meaning, it actually does some different. It behaves differently than every other file. It's kinda like index.html. Remember when we wrote our server, We have that static server that was using the express.static, and I point it to client and automatically served Linux to HTML, because that was the name of the file.

[00:00:50] Well, the convention is kind of the same, and note, if you have a file by the name of index.js inside of a directory, you can just require that directory and it will automatically give you the index.js of that file. So it's a good practice to have like index.js be the root or the entry point to a directory or to a module.

[00:01:09] We won't be doing that, because it's kind of confusing, so you'll be seeing something like this a lot in our code server, server. So it's like going into the server folder grabbing server.js, whereas if we didn't name this server.js, and it was just called index.js, we could just say go into the server folder and it will automatically grab the index.js.

[00:01:36]
>> Speaker 1: Yeah, so new file, index.js, yeah, you had a question, Mike?
>> Speaker 3: He's asking if you use process.cwd to resolve paths?
>> Speaker 1: I wouldn't use that directly. I would use a module that's built in a node, called path, to do that, which does a better job of doing that.

[00:01:55] So, path, require path, I would use this module instead of process.CWD. But if you want to use do manual pros and use current working directory yourself you can totally do that. But also note you have durname too, that's not the full path though, so I would just use path, which does a better job than cwd, but cwd is true, it is valid.

[00:02:26] Yeah, so we're requiring our app here, and we're listening for it, that's what we're doing in this file, in sr.js. So, if you follow this file to server.js, This is pretty much what we built yesterday. Nothing new here. All I did was just take off the listen and export the app.

[00:02:45] But, what is new is expect.js, and it's a testing file. And there's one test in there that is testing the good request to all the lions. Your objective is to make the test for the other four CRUD routes. So we need a test for DELETE, we need a test for UPDATE, we need a test for PUT and we need a test for GET ONE.

[00:03:10] So GET ONE is /lions/id or /tiger/id So, only make those CRUD tests for one resource. So, either do it for lions or either do it for tigers, don't do it for both. If you want to do it for both? Go ahead but it will literally be the same thing.

[00:03:23] You'll just copy it twice with a different URL. So it is up to you. So just do it one time. I started off with lions so you could finish off with lions for the rest of the test if you want to. So, again, you are going to be making a test for a DELETE, UPDATE, PUT, and GET, and if you forget what those things should be doing if you scroll up to our notes that we did yesterday, it tells you right here.

[00:03:44] This is what should happen when we make requests. So if I wrote the test for this one, if I do a get to lions it should return all lions with a 200 with an array. That's what is says here, so if we're gonna look at what's happening here.

[00:03:58] I get get all lions, it should return 200 application.json. That's exactly what it says right here. Application.json. 200. And expect resp.body to be an array. That's exactly what's happening here. So if you forget what you should be tested for, just read this .json file, it will tell you exactly the right test for it

[00:04:21]
>> Speaker 1: As far as, so here's a little bit of clear up on some confusion that might come up. This .expect here is not the same as this expect here. They're the same word but two different things. This .expect method, belongs to request, which is actually super-test, so super-test is a .expect method, so we can expect headers and stuff, but this expect right here is from chai.

[00:04:49] You see the difference? This is a method called expect, this is a function called expect, they just happen to have the same name. If this is confusing, you can change the name of it, In fact, I might even just do that. Just so people
>> Speaker 1: come here. Actually, I'll just change it down here.

[00:05:08] It's too many expects.
>> Speaker 2: Chai is some kind of parsen utility.
>> Speaker 1: Chai's an assertion library. I'll show you what it is. I can show you better than I can tell you.
>> Speaker 1: So, Chai is an assertion library that is specifically made for tests. It gives you this nice syntax to make assertions about objects inside of JavaScript and test them.

[00:05:36] It has three different flavors. So, you can use the assert or you can use the expect, or you can use should. They all do the same thing, it's just a different syntax, which ever one you like. I like expect, so I use it. The documentation for it is here.

[00:05:50] So, It's kind of like reading English, like I expect food to deep equal this object, stuff like that. You can look that up, it's pretty simple, that's why I didn't even bother to mention that.
>> Speaker 2: Mocha has the http stuff And chai handles the dirty work, so to speak?

[00:06:05]
>> Speaker 1: Good question, so mocha, so actually supertest handles the http stuff, this thing right here called supertest which is request. Mocha, is handling the stuff like describe and it. Mocha is actually running the test. Mocha is the thing that's going to run the test. Which gives us these global, that like describe it.

[00:06:26] That's where these words come from. If I were to run this in node, if I were to run this file in node, it would break. If I said node, server, spec, it will break. It will describe as not defined. That is not a word in JavaScript, if I could run this in mocha, it would work.

[00:06:44] Because Mocha gives us describe. It's a global inside of Mocha. So yeah, Mocha is running the tests, which gives us describe. And it gives us the structure. It's the framework, it's the testing framework. Supertest is actually calling our server and chi is actually making the assertions, all right?

[00:07:08] So speaking of, in order for you to actually test this, everyone needs to MPM install, globally, -g Mocha if you don't have that already. So you need to have Mocha globally installed on your computer. So make sure you have that. So again you need to empty and install -g for global mocha.

[00:07:29] Most of you might have to sudo this, so if you need to sudo, sudo, yeah. You need mocha. You had a question Will?
>> Speaker 2: No.
>> Speaker 3: He's asking where in the testing process do you consider load testing? Is that more of an integration type test, or would you consider making it part of your mocha tests?

[00:07:53]
>> Speaker 1: I mean, I guess you could write load testing inside of mocha, but I think there are way better tools that exist out there, then writing. I mean Mocha and Jasmine really wasn't meant to be doing load testing. Load testing is more of a architectural level thing. It's not more of like an internal, I'm gonna test this server type thing.

[00:08:15] It's a little different. I mean you could do it, there's nothing stopping you from just like doing a set interval and just throwing stuff at Mocha or throwing stuff at your server here. But there exists better tools for that so I wouldn't really, I wouldn't handle that here.

[00:08:29]
>> Speaker 3: And then somebody mentioned that, in the notes, you're using .done and code samples are using .end as the last line. Is there a difference?
>> Speaker 1: The notes are using .done. Hold on, we'll see. Looks like, I probably got confused on something .done in the notes. Yeah .done is wrong don't use .done.

[00:08:48] It should be .end. If you use .done it's gonna break. I think I just made a mistake and put .done, because Jasmine and Mocha has this done callback here that you have to call an asynchronous test, and I just mixed the names up. So yeah, don't use this I'll update this though.

[00:09:04] It's not on here but yeah, in the actual app it's right, .end is right. So, speaking of that, because this test is a asynchronous test we have to tell Jasmine and Mocha when it's done and there's a few ways that you can do that. We can actually return a promise, which is newer in Jasmine and Mocha, but we can also just use this callback function they provide.

[00:09:26] I just called it done. So whenever we're finally done with the test, just call done. Now if you don't get rid of this and you try to run the test, I'll show you what happens. I'll just do it right now. So if I said mocha server It just said timeout, it has a timeout default of two seconds.

[00:09:50] After two seconds, it says nothing happened I quit. That's because I never called it done, but if I call done, then it's like yeah, passed. You're test passed, you're good, so make sure you call done and those asynchronous call backs. Any questions for this stuff? So, you have mocha to run the test, I think the notes are in there it tells you type mocha server, server specs, but again that's the command.

[00:10:18] You run it, that one test that I wrote should be passing for you and then you should be writing four other tests. For the other colour routes. So, that means we need to write a test and we hit the URL, and it should delete something, which will also write one that will update something.

[00:10:35] Why did I put? I meant post, not put an update. So create something and also get one, so if you're thinking, like wait, how do I delete something if it's not there? That means that probably before you delete it, you need to create something first. Same thing with the update.

[00:10:55] So before you update it or put it, you need to create something too.
>> Speaker 1: So this is a little tricky. There's a couple ways you can do it, but I'm curious to see how you do it. But yeah You can't delete anything if nothing's there and you can't update something if nothing's there.

[00:11:11] And you also need the reference to the ID to delete something. So, if it is there you need to get the ID of it to pass it on the URL, right? Because that's how our API looks like if we go to our API on, let's just look at delete, delete is expecting an ID here.

[00:11:27] So as put, it's expecting an ID here. So not only do they need to exist you need the ID to reference them too. So, like I said there's a couple of ways you can do that, there's some hacky ways, there's some right ways, but just know that you can always do more than one request inside of and it box.

[00:11:43] Remember that.