Server does not complete setup before next test suite executes in Mocha
See original GitHub issueEnvironment
Name | Version |
---|---|
msw | 0.27.0 |
node | 12.19.0 |
OS | Linux x86_64 |
Request handlers
Note: I have created a repo displaying the behavior here.
App.test.js
import React from 'react';
import { render } from '@testing-library/react';
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import App from '../App';
describe('App tests', () => {
const server = setupServer(
rest.post('http://localhost:8080/api/getList', (req, res, ctx) => {
return res(
ctx.set('access-control-allow-origin', '*'),
ctx.json({
msgCode: 0,
msgDesc: 'Request processed successfully',
data: {
data: {
createdBy: 'CJ',
createdDate: '02/18/2021',
},
pagination: {
pageNo: req.body.pagination.pageNo,
pageSize: req.body.pagination.pageSize,
total: 1,
sortedColumn: req.body.pagination.sortedColumn,
sortedType: req.body.pagination.sortedType,
},
},
})
);
})
);
before(() => {
server.listen();
});
after(() => {
server.close();
});
it('renders App without crashing', () => {
render(<App />);
});
});
Child.test.js
import React from 'react';
import { render } from '@testing-library/react';
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import Child from '../Child';
describe('Child tests', () => {
const server = setupServer(
rest.post('http://localhost:8080/api/getChildList', (req, res, ctx) => {
return res(
ctx.set('access-control-allow-origin', '*'),
ctx.json({
msgCode: 0,
msgDesc: 'Request processed successfully',
data: {
data: {
createdBy: 'CJ Child',
createdDate: '02/18/2021',
},
pagination: {
pageNo: req.body.pagination.pageNo,
pageSize: req.body.pagination.pageSize,
total: 1,
sortedColumn: req.body.pagination.sortedColumn,
sortedType: req.body.pagination.sortedType,
},
},
})
);
})
);
before(() => {
server.listen();
});
after(() => {
server.close();
});
it('renders Child without crashing', () => {
render(<Child />);
});
});
Actual request
The actual request is simply performed on mount via the Fetch API (in our tests we are utilizing the isomorphic-fetch library to polyfill Fetch for Node).
function Child() {
useEffect(() => {
fetch('http://localhost:8080/api/getChildList', {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
pagination: {
pageSize: 10,
pageNo: 0,
sortedColumn: 'createdBy',
sortedType: 'asc',
},
}),
})
.then(async (response) => {
console.log('Fetch complete: ', await response.json());
})
.catch((error) => {
console.error('Failed to fetch: ', error);
});
}, []);
return (
<React.Fragment>
<h1>Child</h1>
</React.Fragment>
);
}
Current behavior
If we are running two test suites consecutively, in this case, App.test.js and then Child.test.js in quick succession, the second server is not fully set up before the test executes, resulting in something like this:
> mocha-ref@1.0.0 test:watch
> cross-env NODE_ENV=test mocha --timeout 10000 -w src/**/*.test.js
App tests
✓ renders App without crashing
Fetch complete: {
msgCode: 0,
msgDesc: 'Request processed successfully',
data: {
data: { createdBy: 'CJ', createdDate: '02/18/2021' },
pagination: {
pageNo: 0,
pageSize: 10,
total: 1,
sortedColumn: 'createdBy',
sortedType: 'asc'
}
}
}
Child tests
✓ renders Child without crashing
Failed to fetch: FetchError: request to http://localhost:8080/api/getChildList failed, reason: connect ECONNREFUSED 127.0.0.1:8080
at ClientRequest.<anonymous> (/home/cjones26/JS/mocha-ref/node_modules/node-fetch/lib/index.js:1461:11)
at ClientRequest.emit (events.js:314:20)
at Socket.socketErrorListener (_http_client.js:428:9)
at Socket.emit (events.js:314:20)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
type: 'system',
errno: 'ECONNREFUSED',
code: 'ECONNREFUSED'
}
2 passing (59ms)
ℹ [mocha] waiting for changes...
Expected behavior
> mocha-ref@1.0.0 test:watch
> cross-env NODE_ENV=test mocha --timeout 10000 -w src/**/*.test.js
App tests
✓ renders App without crashing
Fetch complete: {
msgCode: 0,
msgDesc: 'Request processed successfully',
data: {
data: { createdBy: 'CJ', createdDate: '02/18/2021' },
pagination: {
pageNo: 0,
pageSize: 10,
total: 1,
sortedColumn: 'createdBy',
sortedType: 'asc'
}
}
}
Child tests
✓ renders Child without crashing
Fetch complete: {
msgCode: 0,
msgDesc: 'Request processed successfully',
data: {
data: { createdBy: 'CJ Child', createdDate: '02/18/2021' },
pagination: {
pageNo: 0,
pageSize: 10,
total: 1,
sortedColumn: 'createdBy',
sortedType: 'asc'
}
}
}
2 passing (59ms)
ℹ [mocha] waiting for changes...
Screenshots
Failed test:
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:16 (9 by maintainers)
Top Results From Across the Web
Ensuring server app runs before mocha tests start
Your server module doesn't have a callback, so it could not be ready when you call done() in your beforeEach method.
Read more >Mocha — Global Setup and Teardown (before/after)
Creating a solid test suite for your application may require one or more setup steps before running the tests. Mocha offer two ways...
Read more >Mocha - the fun, simple, flexible JavaScript test framework
When a test file is loaded, Mocha executes all of its suites and finds–but does not execute–any hooks and tests therein. Top-level hooks,...
Read more >Testing Node.js with Mocha and Chai - LogRocket Blog
To complete your Mocha setup, you'll have to write a unit test for a very simple functionality and configure a script to run...
Read more >Configuration File - WebdriverIO
The configuration file contains all necessary information to run your test suite. It's a NodeJS module that exports a JSON. Here is an...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@cjones26 The magic here is the usage of the
--file
flag in the CLI (or inmocharc
in this case). The server creation/cleanups are always rerun and skip the awkward handling of the lifecycle hooks behavior from mocha.This behavior is slightly different than what I did originally where I created the server once, then set it to global.
Either works, but this is the best we can do for now. We’re going to continue to research supporting parallel mode - if we resolve that, I’ll let you know so you can update if necessary. Thanks again for providing this issue!
@kettanaito You might be right, but I’m not 100% sure and it’s kind of a pain to debug. By default, mocha runs sequentially and you have to opt-in to
parallel=true
. This seems to be more of a problem with how mocha is running tests, but I’m no mocha expert.For example, in the repo as-is, if you remove the
server.close()
from each test file, it’ll run them all just fine but would lead to cleanup issues.As an immediate solution that works with both sequential and parallel runs, what I’d recommend @cjones26 does is change the mocha configuration with these steps:
In the given repro, you’d add this file:
Update mocha config to include the new hooks file:
Refactor tests to look like:
and
As general guidance, I’d move the request handlers and server instance creation out into their own files so you can more easily reuse them in other places such as Storybook.