Sinon with multiple mocha test files - node.js

I have multiple Mocha test files using one shared base file known as testBase.js. It's responsible for setting up all stubs and spies.
If I run individual file through mocha all test cases pass but when it run tests through mocha *.js, test cases begin to fail and raise error
TypeError: Attempted to wrap send which is already wrapped
Here are my beforeEach and afterEach blocks
beforeEach(function (done) {
context.alexaSpy = sinon.spy(alexa, "send");
}
beforeEach(function (done) {
context.alexaSpy.restore();
}
I actually printed out logs in both blocks and there is a strange thing I noticed. I see logs this way
-- BeforeEach Fired Test1
-- BeforeEach Fired Test1
-- AfterEach Fired Test1
-- AfterEach Fired Test1
I don't know why it's calling twice and its the root cause of the issue. BefireEach must not call twice for one mocha test.
Does importing multiple files call beforeEach twice? Can someone suggest any possible solution to this? I tried sinon.sandbox too but it does not work

We need to see how you require in the base file to be certain.
My guess is simply that you require the file from multiple files, and each time you do this you add the setup and teardown functions. That happens because all the tests share the same outer scope. Requiring the Base file ten times will add the beforeEach ten times too.
The right way to do this would be using sinon.sandbox or sinon-test. Much easier to avoid one test interfering with the next.
But no matter what you do, you would need to export the function and run that in a beforeEach in each file
Typically like this
const base = require('./base')
describe('module one', ()=> {
beforeEach(base.commonStubs);
it('should.... ',..);
})

Related

"top level" test in jest

While writing integration tests in jest I would like to reproduce the same behaviour I have achieved in mocha by:
mocha -r ts-node/register tests/integration/topLevelTest.test.ts 'tests/integration/**/*.test.ts'.
topLevelTest.test.ts :
let importantVariable;
describe("should do something with my variable", () => {
importantVariable = returnSomethingImportant();
it("should important variable exists", () => {
should.exist(importantVariable)
})
})
after(() => {
importantVariable.cleanUp()
})
Behaviour was simple: firstly topLevelTest executed describe, then other test suites executed themselves, and in the end after within topLevelTest were executed.
In my attempt of rewriting it to jest I wrote something very similar. Only difference is I used afterAll instead of after. The result is: firstly topLevelTest executed describe, then afterAll, and then other test suites. Is it possible to make afterAll run after other test suites?
This is what setup files are for, more specifically setupFilesAfterEnv because Jest environment is already initialized there with globals being available.
Top-level afterAll that wasn't grouped with describe applies to all tests within current test suite. Since Jest tests run in parallel (unless runInBand option was specified) in different threads, it obviously won't affect other test suites.
In case tests need to not proceed if a setup failed and data from setup needs to not be, globalSetup and globalTeardown configuration options should be used for that. This is not a test but the main difference is that describe and separate test blocks are unavailable. Global expect is not available but can be imported, this results in meaningful errors in case a setup fails:
// setup.js
let expect = require('expect');
module.exports = async () => {
let server = ...;
expect(server)...;
global.__MYSERVER__ = server;
};
// teardown.js
module.exports = async function () {
// close __MYSERVER__
};
Since global setup and teardown run in parent process, __MYSERVER__ cannot be accessed in tests.

Is there a good way to print the time after each run with `mocha -w`?

I like letting mocha -w run in a terminal while I work on test so I get immediate feedback, but I can't always tell from a glance if it's changed or not when the status doesn't change - did it run, or did it get stuck (it's happened)?
I'd like to have a way to append a timestamp to the end of each test run, but ideally only when run in 'watch' mode - if I'm running it manually, of course I know if it ran or not.
For now, I'm appending an asynchronous console log to the last test that runs:
it('description', function () {
// real test parts.should.test.things();
// Trick - schedule the time to be printed to the log - so I can see when it was run last
setTimeout(() => console.log(new Date().toDateString() + " # " + new Date().toTimeString()), 5);
});
Obviously this is ugly and bad for several reasons:
It's manually added to the last test - have to know which that is
It is added every time that test is run, but never others - so if I run a different file or test -> no log; if I run only that test manually -> log
It's just kind of an affront to the purpose of the tests - subverting it to serve my will
I have seen some references to mocha adding a global.it object with the command line args, which could be searched for the '-w' flag, but that is even uglier, and still doesn't solve most of the problems.
Is there some other mocha add-in module which provides this? Or perhaps I've overlooked something in the options? Or perhaps I really shouldn't need this and I'm doing it all wrong to begin with?
Mocha supports root level hooks. If you place an after hook (for example) outside any describe block, it should run at the end of all tests. It won't run only in watch mode, of course, but should otherwise be fit for purpose.

How to run 'After' code on Mocha only on specific tests?

Edit: This question was answered, but I have another, similar question which I didn't want to open a new thread for.
I'm using Mocha and Chai to test my project.
As part of my code, I create a new user and save him in our DB (so the test user can perform various methods on our app).
Generally, after every test I would like to run a code block that deletes the user from the DB, which I did using the "AfterEach" hook.
My problem is that I have 1 test (might be more in the future) which doesn't create a user (e.g, 'try to login without signing up'), so my AfterEach code receives an error (can't delete something that doesn't exist).
Does Mocha supply a way to disable the 'AfterEach' on some tests? Or some other solution to my problem.
Edit: Added question: my AfterEach hook involves an async method which returns a promise. On the Mocha documentation I only saw an example for async hooks that work with callbacks. How am I supposed to use an afterEach hook that returns a promise
You can nest describe blocks, so you can group user interaction tests and also group the "with user" and "without user" tests:
describe('user interaction', () => {
describe('with user in database', () => {
// these will run only for the tests in this `describe` block:
beforeEach(() => createUser(...));
afterEach (() => deleteUser(...));
it(...);
});
describe('without user in database', () => {
it(...);
});
});

How to Completely End a Test in Node Mocha Without Continuing

How do I force a Mochajs test to end completely without continuing on to the next tests. A scenario could be prevent any further tests if the environment was accidentally set to production and I need to prevent the tests from continuing.
I've tried throwing Errors but those don't stop the entire test because it's running asynchronously.
The kind of "test" you are talking about --- namely checking whether the environment is properly set for the test suite to run --- should be done in a before hook. (Or perhaps in a beforeEach hook but before seems more appropriate to do what you are describing.)
However, it would be better to use this before hook to set an isolated environment to run your test suite with. It would take the form:
describe("suite", function () {
before(function () {
// Set the environment for testing here.
// e.g. Connect to a test database, etc.
});
it("blah", ...
});
If there is some overriding reason that makes it so that you cannot create a test environment with a hook and you must perform a check instead you could do it like this:
describe("suite", function () {
before(function () {
if (production_environment)
throw new Error("production environment! Aborting!");
});
it("blah", ...
});
A failure in the before hook will prevent the execution of any callbacks given to it. At most, Mocha will perform the after hook (if you specify one) to perform cleanup after the failure.
Note that whether the before hook is asynchronous or not does not matter. (Nor does it matter whether your tests are asynchronous.) If you write it correctly (and call done when you are done, if it is asynchronous), Mocha will detect that an error occurred in the hook and won't execute tests.
And the fact that Mocha continues testing after you have a failure in a test (in a callback to it) is not dependent on whether the tests are asynchronous. Mocha does not interpret a failure of a test as a reason to stop the whole suite. It will continue trying to execute tests even if an earlier test has failed. (As I said above, a failure in a hook is a different matter.)
I generally agree with Glen, but since you have a decent use case, you should be able to trigger node to exit with the process.exit() command. See http://nodejs.org/api/process.html#process_process_exit_code. You can use it like so:
process.exit(1);
As of the mocha documentation, you can add --exit flag when you are executing the tests.
It will stop the execution whenever all the tests have been executed successfully or not.
ex:
mocha **/*.spec.js --exit

Nodeunit - Explicit ending of tests

I have 2 nodeunit test cases in which if first fails i don't want to run 2nd test case.(Process should skip testing 2nd test case with proper result.) How do I do the same.
I have written sample code where In first test case I have specified number of expects should be one. Even if first test case fails, second test case still executes. What could be the issue here.
exports.testSomething = function(test){
test.expect(1);
test.ok(false, "this assertion should fail");
test.done();
};
exports.testSomethingElse = function(test){
test.ok(true, "this assertion should pass");
test.done();
};
Generally it is a bad idea to make separate tests dependent on eachother, and testing frameworks don't support this kind of thing because of that. Nodeunit tests are declared and processed for execution before any one test has started so there is no way to change which tests run.
For that specific example, if the add fails, then it makes sense that delete fails. It might be slightly annoying to get more output, but it's doing just what it is supposed to do.
It may not be applicable in this cause, but one option is to have a separate section for your delete tests where you use setUp to set up everything that delete needs without having to actually call add.
Update
test.expect is used to specify how many assertions were expected in a single test. You only really need it if your test has asynchronous logic. For example:
'test': function(test){
test.expect(5);
test.ok(true, 'should pass');
for (var i = 0; i < 4; i++){
setTimeout(function(){
test.ok(false, 'should fail');
}, 5);
}
test.done();
},
Without the test.expect(5), the test would pass because done is called before the line in the setTimeout has run, so the test has no way of knowing that is has missed something. By having the expect, it makes sure the test will properly fail.

Resources