First of all I already searched for issues and answers on this repository and on Stack Overflow but I didn't find a solution that fit with my needs.
I have to follow these steps:
I have to do this for each user that i fetch from the DB. So i write my test like this:
describe('Starting the server', function () {
before(function () {
// .... code to start the nodejs server
});
after(function () {
// ... code to stop the server
});
describe('Fetching Users' , function () {
return MyDbService.getUsers(myCriteria).toArray().each(function (user) {
describe('Testing the user: ' + user.username, function () {
before(function () {
// ... login
});
after(function () {
// ... logout
});
it('Check policy', function () {
supertest(myServerInstance)
.get('/myRoute')
.expect(200)
});
});
});
});
});
The primary problem is that the first before functions aren't executed, so the login won't be performed. In this way the test will always fail.
So I tried to replace the describe functions with the it ones where I need to execute the before and after hooks.
It still doens't work as I expect. I see this issue. The beforeDescribe could solve all my problems but I saw that it won't be implemented.
So here I am asking: How should I write this test?
The equivalent of beforeDescribe would be to use --delay and refactor the test like so:
// .... code to start the nodejs server
// ... everything else in the callback that will be called when the server has started
(function callback() {
describe("using server", function() {
MyDbService.getUsers(myCriteria).toArray().each(function (user) {
describe('Testing the user: ' + user.username, function () {
before(function () {
// ... login
});
after(function () {
// ... logout
});
it('Check policy', function () {
supertest(myServerInstance)
.get('/myRoute')
.expect(200)
});
});
});
after(function () {
// ... code to stop the server
});
});
run();
});
However, you may wish to refactor your code in one of a few other possible ways:
If the users are supposed to be variable data, you could just write one test that checks all the users:
describe('Starting the server', function () {
before(function () {
// .... code to start the nodejs server
});
after(function () {
// ... code to stop the server
});
it('Testing Users' , function () {
// does this use promises? you will need some way for each step to wait till the previous is done and for the test to finish when the final step is done
return MyDbService.getUsers(myCriteria).toArray().each(function (user) {
// ... login
supertest(myServerInstance)
.get('/myRoute')
.expect(200)
// ... logout
});
});
});
});
If the users are not meant to be varying data but are meant to be a specific set that needs to be tested, perhaps just hardcode them -- in "real" code hardcoding is bad, but a large part of the purpose of test code is to check that what the real code actually has/does is what we expect, and hardcoding that expectation is usually better than having the tests depend on the correctness of complex code (or even simple code if it is part of the "real" code that's supposed to be tested):
var users = [{
username: "admin",
otherStuffNeeded: "whatever"
}, {
username: "example non-admin user",
otherStuffNeeded: "whatever"
}];
describe('Starting the server', function () {
before(function () {
// .... code to start the nodejs server
});
after(function () {
// ... code to stop the server
});
users.forEach(function (user) {
describe('Testing the user: ' + user.username, function () {
before(function () {
// ... login
});
after(function () {
// ... logout
});
it('Check policy', function () {
supertest(myServerInstance)
.get('/myRoute')
.expect(200)
});
});
});
});
Finally, if you're using the correctness of the actual users as a proxy for the correctness of the underlying behavior of the database, you may want to bypass using preexisting users and just try to exercise the database behavior that needs to be correct:
describe("confirming database won't create a user with incorrect policy", function()
before(function() {
// ... code to create and start a dummy copy of the server
})
after(function() {
// ... code to stop and delete the dummy copy of the server
})
describe("User type X", function() {
before(function() {
// ... code to create a user of type X
})
after(function() {
// ... optionally, delete that user
})
it("should have policy etc. etc.", function() {
supertest(myServerInstance)
.get('/myRoute')
.expect(200)
})
})
// repeat for user type Y, etc.
})
// OR
describe("confirming database's business logic won't create a user with incorrect policy", function()
before(function() {
// use something like `sinon` to spy on a mock database
})
after(function() {
// clean up mock/spy
})
describe("User type X", function() {
before(function() {
// ... use business-logic code directly to create a user of type X instead of using a server instance
})
after(function() {
// ... anything to do here in this case??
})
it("should have policy etc. etc.", function() {
// instead of supertest-ing the database content, check the spied data to see that the business-logic code used the database correctly
})
})
// repeat for user type Y, etc.
})
Thank you very much, your solution solve my problem.
Most helpful comment
The equivalent of
beforeDescribewould be to use--delayand refactor the test like so:However, you may wish to refactor your code in one of a few other possible ways:
If the users are supposed to be variable data, you could just write one test that checks all the users:
If the users are not meant to be varying data but are meant to be a specific set that needs to be tested, perhaps just hardcode them -- in "real" code hardcoding is bad, but a large part of the purpose of test code is to check that what the real code actually has/does is what we expect, and hardcoding that expectation is usually better than having the tests depend on the correctness of complex code (or even simple code if it is part of the "real" code that's supposed to be tested):
Finally, if you're using the correctness of the actual users as a proxy for the correctness of the underlying behavior of the database, you may want to bypass using preexisting users and just try to exercise the database behavior that needs to be correct: