In the previous chapter, we learned all that we need to know about Mongoose, MongoDB, and Schemas. We are going to use that knowledge widely to build our Product schema and test it.
We do not want to leave the test till the very end, because sometimes, we tend to skip things that are left for the end. With the test-first approach, our tests will serve as guidelines for things to be implemented. We are going to use Mocha, which is very modular and supports multiple assertion libraries. For testing the models, we are going to use a BDD style assertion should.js
(also developed for TJ). You can study all the possible assertions at https://github.com/tj/should.js.
Now, create the product.model.spec.js
file using the following command:
touch server/api/product/product.model.spec.js
Following TDD, we should perform the following steps:
grunt test:server
.grunt test:server
again; it should pass this time.However, it will be very extensive for this book to go on developing and testing one by one. So, we are going to copy the full product.model.spec.js
file from https://raw.githubusercontent.com/amejiarosario/meanshop/ch4/server/api/product/product.model.spec.js and paste it.
Let's stop here, and explain what's going on. The first thing that you will notice on opening product.model.spec.js
is that we include ProductSchema
, which is a generic schema created by the yo
generator. We will modify the model later to make all the tests pass.
Most of the BDD style tests are grouped in the describe
blocks, and inside these blocks there are it
blocks. They are both JavaScript functions that take two parameters: one is the plain English text string, and the other one is a callback function. The it
blocks are the ones that define the tests in their callback functions. Notice that some of the callback functions have the done
parameter. The done()
function helps us to test asynchronous functions, and when called, it also returns errors with done(err)
. The beforeEach
blocks are executed before each it
block inside their current describe
block. In our case, we are going to remove all the products before starting each test using Product.remove(done)
. The block beforeEach
helps us to test each block in isolation so that the products created in the previous tests do not interfere with the tests that follow.
Run grunt test:server
in the console, and watch how all the tests fail. Here's a challenge: Can you make modifications to product.model.js
to make all of them pass without seeing the solution?
The following changes are needed to meet our (test) requirements:
/* server/api/product/product.model.js *excerpt */ var ProductSchema = new Schema({ title: { type: String, required: true, trim: true }, price: { type: Number, required: true, min: 0 }, stock: { type: Number, default: 1 }, description: String });
Now all the tests should succeed and will look similar to this:
Product ✓ should not create without title ✓ should remove trailing spaces from title ✓ should default stock to 1 ✓ should not create without price ✓ should not allow negative price ✓ should save a description
The tests have now documented our Product schema describing what our products do and what it validates.
Running grunt test:server
, made the Products tests succeed but it broke the product.integration.js
tests. Let's implement the API and fix that.
18.225.255.187