Add unit tests to a LoopBack API project

Bram Borggreve
InstructorBram Borggreve

Share this video with your friends

Send Tweet
Published 5 years ago
Updated 3 years ago

In this lesson we will learn how to add tests to the project to make sure our API behaves as we expect.

After installing mocha and chai as devDependencies we will add test and test:watch scripts to our package.json. We will create a different datasource what we will use when running the tests by copying datasources.json to datasources.test.json and prefixing our test command with NODE_ENV=test.

We will verify that our tests run against an empty datasource. We’ll also add various tests to verify that our remote method and validation on the Product model behave as expected.

[00:00] We install Mocha and Chai as devDependencies. We open up our package.json and modify the script section. We remove the post-test script and add a test script. The test script runs Mocha on all the files with the extension .test.js in the test folder.

[00:16] We also add a script, test;watch, that runs the npm run test scripts, and passes in the watch parameter to Mocha. We create a file test/common.js, which will serve as a helper for our tests. Here we create a reference to our LoopBack server called app.

[00:33] We require Chai, and get expect from Chai. In the last step, we export app and expect, which we will use in our tests. We create the file test/unit/product.test.js, and in that file we will create our first test. We include app and expect from common, and we will get a reference to our product model.

[00:54] We add our first test, and in this test we will call into the product model and call find, and we'll log out the results. When we run npm run test, we see that we get an error message. Error message says that it can't find any files matching the pattern.

[01:08] We look in our package.json. We see that we made a typo here. Let's fix that by using the right path. When we now run our test, we see that we pass. What this test also shows is that it uses our default database connector. One way to fix this is to override the data source for a specific node environment.

[01:26] In our package.json in the script section, we override the environment of the test commands by prefixing the commands with NODE_ENV equals tests. This means that Mocha will run using this NODE_ENV.

[01:37] We copy servers/datasourcestoJSON to server/datasources.testofJSON, where test is the name of the node environment. In our copied file, we set the DB connector to false. When we run our test again, we see that it passes and that our test returns an empty array.

[01:57] Let's run our test in watch mode, and add some actual tests. In this test, we test our instance methods. We create a new instance of the products with these parameters, and run the buy method on the instance.

[02:10] As a parameter, we pass in the quantity of 10. In our callback, we verify that we have the right return status. In our second test, we initiate the same product. This time, we run the buy method with a negative amounts. In our callback, we verify that we get the error that we expect.

[02:27] Now, let's add some tests to ensure our validation works as expected. We test if our product name has the expected length. We do this by calling into the product.create method with a new product as the payload.

[02:39] Product.create returns a promise, and in the catch block we verify that the error message and the status codes are as we expect. We do the same for duplicate name. We start our promise chain with a promise.resolve, and then we run product.create twice with the same product details.

[02:56] In the catch block, we verify our error message and status code again. Here we test the product price. We test the same way as with product name, but this time we enter a price of less than one. The error message should contain the string, "Price should be a positive integer."

[03:10] In this test, we verify that we cannot add a price lower than the minimum of 99. For good measures, we also add a test to verify that a correct product gets added in the way we expect it to.

~ 4 years ago

@Graeme, the buy function should run well, you are passing the error as second argument when the fact of the callback is to have first argument just when there is an error and you will check it latter like:, result) => {
  if (err) throw err; // throw the error and stop the execution
  // You probably don't whant this line to be executed if there is an error

/** more code
~ 4 years ago

no (res.status) - just (res)