Check out a free preview of the full API Design in Node.js (using Express & Mongo) course:
The "Testing in Node" 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:

Unit testing in Node is very similar to unit testing in the browser except for the absence of the DOM. To make the testing process easier, Scott recommends exporting the main application so it can be used by the testing framework. He also covers a couple strategies for writing API tests and saving development dependencies.

Get Unlimited Access Now

Transcript from the "Testing in Node" Lesson

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

[00:00:03]
>> Scott Moss: So if you want to check out to Step five, yeah that's it. We'll hop into testing. But, before I set you loose and actually start writing some tests for the lions and tigers API that we built, let's just walk through what testing is and how it works.

[00:00:21] With Node and Mongo and the different types of testing, and what we're actually gonna be testing, and stuff like that. So testing is actually pretty simple in a node. In my opinion, actually, from testing other languages and other environments. And Node is pretty straightforward compared to other things like for instance writing test for Android or something like that, node is actually pretty simple.

[00:00:46] Unit tests are very similar to how you would test in the browser minus the DOM. So if we were gonna unit test our JavaScript here on node it would be pretty much the exact same thing if you were unit testing in the browser, without the DOM. For instance, if you providing test for browser code, four or five years ago, before Karma came along and all the other stuff, you would, you know, use Mocha or Jasmine.

[00:01:12] Well probably not Mocha, but something like Jasmine and it'll generate an HTML file for you where you loaded up all your specs and loaded up all your source code, load up all your dependencies, and you open that file in the browser, and then you run the test suite through there and have a nice UI, right?

[00:01:26] And then Karma came along and was like we can do it from the command line now and we'll just pipe it to a browser. But, as far as like the experiences like writing the test itself it's pretty much the same and that's mainly due to the fact that it's still just JavaScript.

[00:01:39] So, unit tests are somewhat the same minus the dom, which probably makes it easier cuz there's no dom. It's just pure function. Integration testing is what we actually start testing the API and what it does when we hit those routes, right? So unit testing is testing specific units in our application like this function should do this, this object should have this, stuff like that.

[00:02:00] Integration testing is like all right we're just gonna test the API from actually hitting this route to see what the database responds with, right? We're gonna do integration testing. We're going to do integration testing, mainly because the code we've written so far we haven't written a lot of code, actually most of the code that we have written is part of express.

[00:02:19] So we start unit testing we'll just be unit testing what express is already doing, and that's already well tested. We'll just be doing integration testing to see what our api responds to when we throw different parameters at it, and what we expect to come back to. Any questions so far on that?

[00:02:41] Yes.
>> Mark: Is integration testing a synonym for BDD?
>> Scott Moss: Behavior driven development? I wouldn't say it's a synonym. It's part of BDD, but I definitely wouldn't say it's a synonym. BDD is more than just integration testing, it's just BDD is like a style of testing, or actually TDD is like test driven development where like you're gonna write some tests first.

[00:03:02] Like red, green refractor with TDD. Write a whole bunch of tests and then have the tests tell you what code to write to get to get them to pass. BDD is more like, we expect this thing to happen so we are going to write a test to dictate this entire behavior.

[00:03:18] But, yeah, integration testing is part of BDD but they are not the same thing. Integration testing is a type of test, BDD is how you write tests.
>> Scott Moss: Great, so a good practice with node in Express and integration testing from what I've witnessed is if you export the app before you're starting it.

[00:03:45] So like in our application that we wrote yesterday. We were at the bottom of the file down here, we were like app.listen, we're listening to some port or something. All right, that's how you start the server. But when we're testing it, a good practice is actually to, instead of listening to the server right there on that same file.

[00:04:09] Let's just export the app so it can be required somewhere else. I'll show you why that makes sense but the big reason is really so that our tests can actually use that app and all the routes on it to make assertions and go ahead and start the server for us.

[00:04:27] So, if we just export the app before starting it, we can actually just run the test without having to start the server manually we can just have the test do it for us. So what I'm saying is we set up our routes like this and then at the bottom we would just export the app.

[00:04:40] So that also implies that we would have to make another file that would import this and start the server, of course, which is as you'll see is actually pretty good. Once you see we'll start making a pretty sophisticated API that's a good practice as well. Any questions on that?

[00:04:57] Does that not make sense to anybody? Why I think exporting the app is a good idea. We want to expose our entire server application to like our testing framework. So if I export it I can do that. You can also just start the server too and then export the app.

[00:05:12] There's nothing wrong with that but I would just leave it up to my test to figure out what it wants to do. Maybe the test wants to start the server with a different port or a different configuration, stuff like that.
>> Scott Moss: So, strategies for actually testing our APR are pretty simple too.

[00:05:33] It's exactly how you were testing yesterday, so we're using like post man or httppi, you were coming in here, you were doing something like http and localhost to your port and you put like slash tigers, right. And you do like a get request to that. And you want to see what comes back.

[00:05:56] You actually just, that's what we're going to do for the test. But you visually looked at what came back. You're like, ha ha. That worked. That's exactly what I expect it to be. You looked at the headers, all that stuff. That's exactly what we're doing when we write the test.

[00:06:07] It just that we're visually not gonna be looking at it. The test is gonna be looking at this stuff. So we can use a combination of frameworks like jasmine or mocha an assertion library if we don't have one. So if we use jasmine with an E that should be E there.

[00:06:22] Jasmine has an assertion library built into it but if you use mocha you have to provide your own assertion library, so we've been using a combination of that stuff. And then we're gonna also use something like supertest. This is a framework that's built on top of a framework.

[00:06:36] So there's this request framework for Node that's called superagent. You can think of it as like the AJAX for your server. That's pretty much what it is. It's like the AJAX for your server. It's actually built by the same person who made Express. So there is this thing called super agent and then on top of that there's this thing called super test which allows us to test our application also built by the same person who made express, that's why these two work so well together, because super test is made to work with express.

[00:07:02] So that's what we're going to use: Mocha, Chai, and Supertest, to perform integration testing on the code that we wrote yesterday. So here's an example of what a test would look like. So, first thing we do is reacquire our app. And the reason we can do that is because we exported it up here.

[00:07:26] This is why we exported it. Because now we can reacquire it. So now, we have our application. Our server requires supertest. Mocha's already loaded up and then we're just going to write our test suite. In this case, we're talking about todos so we describe our todos. We make an insertion here.

[00:07:46] It should get all todos. So we make a request to our app, it's a get request. So this URL, we're going to set some headers here. And then we're going to make some assertions right here. So we expect the content type to pass this regex, which is a JSON.

[00:08:08] So we expect the content type to be JSON. We expect to get a 200 back from the server. And then done, we also get to inspect this response object, right here. This response object is what the server sends back so now we can go ahead and make assertions on that.

[00:08:24] Now I can say, I expect the response.id to be defined. And then done, so this is a arbitrary test, so you can do stuff like this. Yeah question Mark.
>> Mark: A couple came up here. If using a testing module should we put that in our dev dependency instead of dependencies?

[00:08:43]
>> Scott Moss: If using a testing module like chai, and yeah, yeah. So if you're using anything related to development or testing yes that should be in your dev dependencies, so the way you would do that is when you MPM install. So if you were going to MPM install something for testing you say MPM install, and you can do dash Uppercase D.

[00:09:05] Or you can do dash, dash save dash D, or dev, and then the name of the package. And that will save in your dev dependencies. So yeah, if it's for testing, it's definitely dev dependencies because your app actually doesn't need it to run. It's only there for testing.

[00:09:22] But you don't need it to run, so you see it in dev dependencies. Good question.
>> Mark: And the next one was, on testing frameworks, could you comment on the benefits of using something like Mocha Jasmine versus something that gives you less for free, like Tape?
>> Scott Moss: Tape is actually pretty awesome.

[00:09:39] I just started using tape a month ago, but I don't know it well enough to recommend it. And I didn't really know its benefits until I used Mocha and Jasmine for so long. But as far as Mocha and Jasmine, Jasmine was the first one, and it's the full suite.

[00:09:53] Jasmine is the one, it was like we're gonna use this to write tests like this. Describe it, all this cool stuff. We're going to supply you with an insertion library. And then Mocha came along, written by the same person who wrote Express. Or I think he's more than one person to be honest.

[00:10:07] It's a group of people with the same name. But he came along and they were like, we're going to write something just like Jasmine with the same syntax so it's familiar for everybody. But then we're not going to require them to use all the built in tools. We're gonna allow them to use whatever they want, so Mocha is just like Jasmine, except it doesn't come with an insertion library, a mocking library, and stuff like that.

[00:10:30] So you gotta go get your own. So if you want the full suite, use Jasmin, if you wanna use your own third party stuff, use Mocha, and as far as Tape, I prefer Tape these days, it's actually my go to now so.
>> Mark: Another one rolled in here right at the end too.

[00:10:51] When we're running the server in the workshop the program will use all the modules in both dev dependency and dependency. But in, when in production, it only uses modules independency. Is that right?
>> Scott Moss: That's not entirely true. It depends on what environment you deploy in. So for instance, let's say Heroku.

[00:11:10] If you deployed Heroku, by default, Heroku will run NPM install production. So it'll only install, you're dependencies inside dependencies, not dev dependencies. But if you're here and you run NPM install it's going to install every single dependency whether it's dev dependency or a real dependency, so it's and you can also tell it, you can force it to install which ones too.

[00:11:33] So that's not entirely true, it depends on what platform you're going to but you can always override those commands, but that is the reason why those two differences exist so you can like Figure out which ones you wanna install. So, I wouldn't say that that's guaranteed, but by default yeah, that might be the behavior of some platforms like Heroku, but again, you can override it.

[00:11:52] So yeah, we'll talk about environment variables and how to trigger those things in a minute.
>> Scott Moss: Cool. So yeah, here's a basic test. It's doing exactly what we would do. We're gonna make a get request to this url, and we expect all this stuff to be true. Or to be whatever we set here.