TDD With TypeScript, Express, NodeJS, and Mocha Unit Tests | Ultimate Full-Stack JavaScript Setup

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
everybody welcome back to the channel today we're going to be making a boilerplate for a typescript express uh mocha node project setup so i've been building full stack javascript applications for the past year or so like on my day to day that's been a real struggle let's get a really good development setup going and i think i've got a pretty good one down pat using tight script and test driven development approach using mocha as the test runner so that is going to be what we're building today the first thing i'm going to do is just make a directory on my desktop here called ts express cd into that uh obviously you should have node installed um that's kind of all you need on your computer at this point though um we'll go through everything um from from there i'm just going to npm init a new project here just gonna go through all this really quickly not only to worry about any of that right now okay and i will open this up in code as well our folder here cool okay so the package.json here from that npm init back to our terminal and we're going to need some dependencies so the big ones are going to be express and dot inf dot environment whatever it's called uh basically just so we can use our environment variables in our project okay and we're also going to need some dev dependencies so using the dash d flag for that uh we're going to be using mocha as our test runner i'm using the chai assertion library with that we're gonna need typescript obviously oh so much harder typing under pressure and then we're going to need nodemon if you haven't used nodemon before it just allows you to um so when you're running your project you make any changes to your files your folders it'll update your project as you are doing those like automatically you won't have to restart your project every single time you make a change we're also going to use supertest supertest just allows us to test endpoints in our in our mocha test so we can actually like you know test out our apis uh we're going to need ts node that's going to let us use typescript in our node project and we're going to need ts uh config paths uh why i use this one is because it allows me to use absolute imports all throughout my node project as well as in my mocha tests i don't have to use the whole like const you know some module equals require yada yada yada so i'm going to download those just take a second okay cool or packers.json and that's got everything we need um oh also we're using typescript so we're going to need to um if you're using typescript you can't you need to import the types for the um for the different libraries that you're using so we need the type declarations so typescript knows the types that it should expect like from those things that we've just downloaded because it's not just like javascript where you can just anything goes it has to be a defined type it's a statically typed language so we're going to do again a dev dependency here we're going to need types slash chai type slash mocha type slash node types slash what else i need here uh super test and that should be it okay now we're good to go now the other thing we're going to need is some scripts here and able to be able to run this with a typescript so um for our build script uh typescript has this handy little compiler that you can run type script compile we're gonna do that for our development purposes this one gets a little crazy but i promise you it is worth it so what i like to do is set my node environment to be dev i'll then use nodemon start the server okay this one here is where remember that ts config paths i mentioned this is going to allow us to use absolute imports everywhere so we're going to use dash r for cursive ts config paths we're going to say slash register and we are going to uh the file we're going to use as the entry point is going to be in crc slash app.typescript we haven't made that yet but we're going to get around to it okay we're also going to initialize a typescript config for this project so we're going to go back to our terminal we're going to run tsc dash dash init and what this is going to do is create us a nice little uh typescript config file that we can go in here and make edits too so there's a couple things we're going to need to do here um the first of which is we're going to need to change our output directory so when typescript compiles it's going to output a bunch of javascript that can actually be you know usable on the browser so we're going to put this in the dot backslash dist folder and that will show up in here when it compiles oh we haven't done it yet so it's not there uh our root directory so this is where our source code is going to be living we're just going to put that in crc uh nice thing always want to keep this to true that's going to give you it's going to it's going to give you all the powers that typescript likes to enforce it's going to make sure you're writing everything very statically typed module resolution is the next one we need to change that as node put that back in there and then the base url okay so this one here the base url is going to give us those um absolute import power so base director to resolve non-absolute module names that's going to come in very very handy later and with that we should be good to go so a quick review here uh this is going to be where our compile type script outputs to this is going to be the source code for our typescript files and we're using node as the module resolution and the base url is the dot backslash crc when we're using absolute imports okay so we're just going to save that up and close it okay the next thing i'm going to do is build out my test script and kind of explain what's going on there because there's it's it's quite a big script the reason i like to do this is because i'd like to develop tdd style so i write tests before i write any source code and you have to write test i need to get my test runner set up so just like before i'll go node environment equals test this time i'm going to run mocha a nice flag i like to put in here is check leaks this is just going to make sure i'm not leaking any global variables and doing any like sort of bad practice mocha stuff it'll just flag it if you're doing anything like that uh the next one i'm going to do is the same as um above ts config path slash register and that's going to give me that absolute import goodness another one i'm going to do is register ts node and last but not least this port part is super this part is super important so what mocha is going to do is it's going to look for a it's going to look under your test directory but what we wanted to do is to go through that test directory and loop through every single file we have in there so if i go into my sidebar here and make a folder called test let's say we create a file in here that's like index dot spec dot ts well we also want to be able to go run through any folders we create so if we create a folder here called like server and create a server runs dot spec dot ts we want to make sure it runs through all of these tests in the directory so we're going to use a little bit of i think this is technically considered rig x i don't know but it's going to be test slash star star dot spec dot ts okay so what this is going to do is going to look in the test directory it's going to look for any subfolders and anything matching the dot spec dot that should be a dot dot ts extension it's going to execute those tests so if we save that up okay so now if we go into our test folder and create a folder here called server and go into the server run spec i have a describe in here and we're just going to run a couple example tests here to make sure everything is working comma there and the first thing we're going to want to do to test this application is just make sure that the server is created without error we obviously don't have any code for this yet but we're going to write the test first because that's dvd ah excuse my terrible typing this is my first coding tutorial and uh we're just going to console log out here to make sure everything is working and just for good measure let's copy this and put it in our index spec just to make sure all the tests are being run in every uh directory so we'll just call this test and this testing now if we go to our terminal and run mpm test you can see that it is running both tests so it's actually going through the entire directory and running uh every spec file you have in there that's great okay um i am going to get rid of this index back here we actually don't need it we know that that's working and go back to our server run spec so okay hold on tdd uh code write test before you write any code so what i'm going to need to do here i just want to make sure that my server is running so i just want to be able to make a get request to the base route of my server so the first thing i'm going to do here is import super tests i'm going to need that test any of my routes call that request you can obviously call if you're familiar with imports you can call this whatever you want it's just the default export from supertest and we're going to also import expect from the chai assertion library and this is just going to be used for some validations on my request okay so what we want to be able to do is make a request to our application uh to be a get request and we just want to return to return a 200 just so we know the application's running so what that is gonna look like is a request to our app dot get it's the base url and we're going to expect this to be a 200. oh another thing is when you are doing any async stuff like this in mocha you can pass in this done function and just call it when it resolves okay obviously we don't have the application yet we haven't written any code so that's what we're going to do next so the reason i love test driven development is because it makes you write testable code so instead of just like creating a server and having it just sit there we're going to actually export it and be able to instantiate at any point to run our tests on it so really every single time we run a test we can create a new instance of the server if we wanted to so we're going to come back to this and dive into creating the server okay so i'm going to create a new folder in my project i'm going to call this crc and in here i'll create a server.ts okay one thing i did forget while i was doing all of my dependencies is the types for express so we're going to do mpm dash d for a dev dependency and that's at types slash express so we are going to need that one okay now i've created a cscrc folder in the base of my application and a server.ts file that's going to be responsible for creating the server okay so we're going to import express from express and we're going to grab some types too because this is typescript after all we need application we're going to need request response next function and application is the first one we're going to be using that just uh is for creating the instance of our app request and response you should be pretty familiar with if you use typescript before as well as next function these are just the parameters you pass into your express routes so we will export a default function here and we will call this create server now the big thing to mention here is that this isn't going to be responsible for um creating us like you probably if you use express you're used to like app.listen on port 4000 if you're not don't worry about it we're not going to make our server like listen on a port here we're going to be creating an instance of the server and we can use it for our tests as well so we're going to call it app and this is going to be of type application equal to express okay uh we'll create a base route for this so app.get this is going to be a request of type request response of type response and next of type next function and let's do an arrow function here and all this is going to do is go res.send and we're going to say hello world okay that's all we're going to do for now and oh this is also going to return the application okay so we've imported our types from express that we have over here in our handy type set express and then we're creating an instance of the application we're defining one route and then we're exporting this okay so what i can do now is i can go over to my server spec and go import create server from server and you will notice that we don't have to use require statements and automatically picks up a server because we set our base route as crc and now we can define an instance of our application so cost app equals create server and that should be it so we run our test suite we have a test passing so uh this function just creates an instance of the application defines one route and then we run one test to make sure that that we are able to instantiate that and create that row okay first test done okay the next thing i'm going to do is register a couple more routes for this application so i'm going to write the test first because that's what we do i'm going to create a new folder i'm going to call this routes um i'm going to just make a um an off route so we're going to make a new folder called this off this is all just pretty generic most applications usually have an auth folder so i'm just going with that one and inside auth i'm going to create an index dot spec dot ts uh no particular reason just usually when i have a test suite um in the folder i'll usually have the index as an entry point or the first if there's only one test in there that's usually i usually go with index as my go to okay so uh just like before we're going to import request from super test uh we're going to be using try again so expect ah oops can you guys tell that i'm taking a peek at my github repo while i'm typing and then import create server see this is why i love tdd because now i can just create an instance of my server whenever i need it because i had to create it that way to run the tests okay so we have our instance of our app set up there and um we're just going to be testing um a route on the uh auth route and we're just going to be sending back a 200 response again the whole point of this isn't you know how to write express routes and do like build some crazy application just giving you guys a boilerplate first getting set up with this kind of stuff okay so we will call this offroads pass in a callback function and our first test we will say off responds with 200. pass another callback function pass in done this is doing some async stuff some semicolons down there for my sanity and then we will make a request app dot get uh this will be going to the auth route and we expect that to be 200 done okay uh so we have written our second test this is obviously going to fail that's test driven development now we go write the uh we go write the code with just enough code to pass this test one of the rules of test drone development is you write your test first and then you write just as much code as you need to pass those tests so you're kind of bouncing back and forth between your tests and your source code okay so how i like to set up my routes is i create one file that kind of pulls in all of the routes and then combines them together and then i can just have one nice little import from my server file so i'm going to show you guys how i go about that so in my crc i'm just going to create a folder here called routes and then i'll create a new file called index.ts and then i will also have my so this is where the auth route is going to be defined and in my index.ts i'm going to be pulling in that route and that way if i ever decide to add like a user route or a dashboard route let's pull all it all into the index i export it and then in my server file i just have to import that one route that i've defined like kind of combining all of these other ones so i'll show you it sounds a little complicated it's actually really easy i'll show you how i go about it here so i'll first just uh work on this authro i think it'll start to become a little more clear to you guys router so we'll need our types for our typescript here import router request we need response and that's all coming from express i want to declare a router and then we will define our first route so i like to comment these so this will be a get request description authenticate user we're not actually building this functionality but and then the access here is going to be public so there's no sort of um like authentic there's no sort of like middleware going through it's not a protected route okay so oops we're going to define our route here the other dot get and we're just going to be using the um so this is just going to be the base route of the auth route um so this will make a little more sense why i'm just putting a slash here i'm not putting slash off that'll make a little bit more sense in a bit when i kind of pull all these together into one route that i just pull into my server file so you guys have probably used express before so i'm just going to kind of zoom through some of this it's going to be request of request type response type arrow function here and all we are going to do here is res.send 200. okay so that is our auth route and then what i'm going to do next is pull all these into our index or pull this route into our index file so i need to export this and this way if i define any more routes down here i can export them all in one shot at the very bottom here so we go back into our index file i'm going to import router again from express and i'm also going to import the router that i exported from off okay there's that guy i'm going to declare another router this might seem a little strange but just bear with me i swear it'll all make sense very quickly and then we're going to say router dot use and we're going to use uh the off route with the auth route that we just exported and we're going to export all of this from this file and we're going to fix our typo okay so what is happening here in our auth file we declare a router we declare one route and then we export that in our index file we bring in that route and we use it in this router that we've created here and we export them all the beauty of this is if you create like a dashboard ts here and export another base route you can import dashboard from dot slash dashboard and then down here you could use like router dot use dash dashboard with the uh dashboard um export and you just keep doing this over and over again for as many as you need and you can even go like uh more folder levels deep in this you could have like route slash dashboard wrote slash auth and then have individual files in there and when we do it this way i'm just going to save all here go back to our server we can import our routes slash index and all we have to do is go app.use all of those combined routes and it's just one line in your server file so no matter how much crap you have going on in your routes folder it's just one import to use all of those routes okay so you guys might have noticed i made a typo here this should be lower case not the router type but actually exporting the router that we declared so now we can go in here and run a quick test and see that our auth responds with 200. so our server is now pulling in the route that we declared there and we could just do this over and over and over again so just to illustrate that if we go in to our routes and create say a dashboard dot ts just arbitrarily and we can just sort of copy this guy for the most part let's call this dashboard 7200 in our index import dashboard from dot slash dashboard and then all we have to do copy this guy down tell express to use these routes on the dashboard path and if we go over into our routes create new folder dashboard create new file that's index dot spec dot ts and same sort of deal check this in there we'll call this the dashboard routes and make sure that dashboard responds with 200 make sure this is set to dashboard and with any luck that test should pass too hey there we go okay so we didn't have to change anything in our server file to make any of that happen because we're just have this one global routes that we're pulling in from the routes dot index okay now that we have our create server set up um our create server function set up and our tests working i'm going to go ahead and create sort of the entry point of the application that'll actually have our server listed on a defined port so the first thing i'm going to want to do actually is create a dot environment file and i'm just going to define a port in here we'll say 5000 and then back in our crc i'll create a new file and i'll call this app.ts this is going to be the main driver of this application so in here we are going to want to import express express again we're going to need application request response and next function we'll also need our create server [Music] function create a server from server and then we're going to create a new function here called start server there's an arrow function and in here we're going to create an instance of our server a big thing to uh get across here this is creating an instance of our server we haven't actually made this server listen on a port on the machine yet the port we're going to use it's going to be a number and this one is a little tricky because if you just do something like process dot environment dot port for default to 4000 typescript is going to complain because process.environment.port in node.js is defined as string or undefined and that doesn't map to number neither one of those things mapped to number so we need to do a little bit of finicking here so we are going to use parse int i'm gonna bring that around here string and so if you look in the documentation for parse in you can opt you can optionally pass it two parameters uh one of those is going to be a string and then the radix so what all the radix is doing is basically saying like what kind of string that's expecting here you can look that up if you want to but this is just the way to get around that whole casting of a process environment variable to a number okay so we're really interested in here is we're going to say call app.listen we're going to listen on the port we specified and then when that completes we're going to pass a callback function in here and we're just going to say console.log and we'll say server running actually we don't want to make these regular quotation marks i want to make these back ticks server running on port just because we want to use this string syntax here and if you go back to our package.json okay so this is all this is all ready to go if we go back to our package.json in our development script it uses the app.ts in the source folder okay so now all we have to do is call this function another thing i forgot that i should put at the top of this file is to import dot dot environment and what that's going to do is it's going to register the port number that we declared and then go back to terminal you should be able to run that dev script run down and it should be running on port 5000 and there you go okay so that is it for the purpose of this tutorial i'm just creating a boilerplate um for you guys to be able to get started using typescript uh test driven development and express this is my first coding tutorial so uh there are going to get better it's a lot harder than it looks but hopefully you guys can take this and go and use it as like a boilerplate for any like express type script uh applications you guys want to go ahead and make um i found this to be pretty much the only development environment that i can like work with sanely in javascript the typescript stuff seems like a lot but it's well worth it you run into more problems at compile time than debugging later at runtime which is much preferable and much more preferable in my opinion and the test room development can be it can be a little cumbersome but like i said it makes you write a lot cleaner code so yeah hopefully you guys like this one uh thanks for watching and i will see you in the next one alright bye
Info
Channel: Darian Sampare
Views: 8,624
Rating: 5 out of 5
Keywords: typescript tutorial, express typescript, express ty, node typescript rest api, node typescript tutorial, node typescript, mocha typescript, full stack javascript, tdd with mocha and chai, tdd typescript, tdd nodejs api, tdd express js, tdd express, javascript testing, unit testing, js testing, unit testing typescript, unit testing mocha chai tutorial, unit testing express js, unit testing node js express, unit testing node js, full stack javascript tutorial
Id: QVxxgEyZt9Y
Channel Id: undefined
Length: 35min 45sec (2145 seconds)
Published: Tue Nov 10 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.