I'm using supertest to unit test my server configurations and route handlers. The server configurations tests are in test.server.js and the route handling tests are in test.routes.handlers.js.
When I run all the test files using mocha ., I get EADDRINUSE. When I run each file individually, everything works as expected.
Both files define and require supertest, request = require('supertest'), and the express server file, app = require('../server.js'). In server.js, the server is started like so:
http.createServer(app).listen(app.get('port'), config.hostName, function () {
console.log('Express server listening on port ' + app.get('port'));
});
Is there something wrong in my implementation? How can I avoid EADDRINUSE error when running my tests?
mocha has a root Suite:
You may also pick any file and add "root" level hooks, for example add beforeEach() outside of describe()s then the callback will run before any test-case regardless of the file its in. This is because Mocha has a root Suite with no name.
We use that to start an Express server once (and we use an environment variable so that it runs on a different port than our development server):
before(function () {
process.env.NODE_ENV = 'test';
require('../../app.js');
});
(We don't need a done() here because require is synchronous.) This was, the server is started exactly once, no matter how many different test files include this root-level before function.
Try requiring supertest from within a root level before function in each of your files.
Answering my own question:
My supertest initialization looks like this:
var app = require('../server.js');
var request = require('supertest')(app);
In test.server.js, I had these require statements directly inside a describe. In test.routes.handlers.js, the statements were inside a before inside a describe.
After reading dankohn's answer, I was inspired to simply move the statements to the very top outside any describe or before and the tests all run without problems now.
Related
I have 2 variables in env file. For Port and mongoDB link. I have tried many solutions on the internet but i am not able to access the values in the listen method nor in database connection.
Here is my sever file code:
const app = require("./app");
const connectDatabase = require("./config/database");
// Config
require("dotenv").config({ path: "backend/config/config.env" });
// Connecting to database
connectDatabase();
app.listen(process.env.PORT, () => {
console.log(`Server is working on http://localhost:${process.env.PORT}`);
}); // I can run the app if i use any port number in place of "process.env.PORT"
Note: I have put the wrong password here to hide my credentials.
I have tried to use env file in root directory also but it did not resolve the issue. The thing is i can access the values in the console but not in the listen method or in connection method.
I can run the app with direct values.
Here is the listen method error screenshot:
Right now you are passing 3000; to the listen function, you need to pass 3000.
Remove the semicolons ; from the env file and it should work.
Have a look at the dotenv npm page here for examples.
Also, you have posted your mongodb credentials online, I'd suggest you change those immediately.
I am new to js and I am trying to develop a simple node.js-mysql app. No matter what I do I can't get the standard
var express = require("express");
statement to work.
I have installed node.js and express correctly, express is in package.json. I have a local server running. But this simple line will not work.
On the node.js side at Windows command line I have no error but when I go to localhost:3000 on the browser, I get
'Uncaught Error: Module name "express" has not been loaded yet for
context: _. Use require([])' error at js console.
I tried changing it to
require(['express']`, function (express) {}
as suggested at node.js web site but then at the Windows command terminal I get a different error saying like
'expecting a string but received an array....'.
I have tried import instead of require and I have tried every suggestion that I could find on the Internet. I have been blowing my brains for weeks to get this to work with no success. I am so frustrated that I am seriously thinking about giving up all together. If someone can help I will be forever greatfull to him/her.
My main js code is as follows:
var port = 3000;
// Import or load node.js dependency modules.
var express = require("express");
var app = express();
var path = require("path");
var bodyParser = require("body-parser");
app.use(express.urlencoded({ extended: true })); // to support URL-encoded bodies.
app.listen(port, () => {
console.log(`server is running at http://127.0.0.1:8887`);
});
app.get('/', function(req, res){
res.sendFile("D:/Behran's files/Web projects/havuzlusite/index.html");
});
Require.JS is for loading AMD modules (and is, honestly, obsolete in today's JS landscape).
Node.js modules are either ECMAScript modules (which use import and export) or CommonJS modules (which use require and module.exports).
Even though both AMD and CommonJS modules use a function named require they are not compatible.
There are methods you can use to run ES modules and CommonJS modules in the browser however they can't replace APIs that are provided by runtimes.
Express.js needs to be able to listen for incoming HTTP requests. Browsers do not provide any mechanism to make that possible. Node.js does.
If you want to run Express.js you have to run it using Node.js and not a browser.
Express.js creates an HTTP server. A browser can make requests to it (e.g. if you type http://127.0.0.1:3000 into the address bar.
(Your code says server is running at http://127.0.0.1:8887 but the port constant is set to 3000).
All your Express.js code must run through Node.js.
You can't send a copy of that code to the browser and run it there too.
I'm using jest to write some tests for a node.js application. I have a server server.js and a test file server.test.js. In my server.js I use the line
var secureServer = https.createServer(options,
app).listen(config.node_port, () => {
logger.info("Service running on " + config.node_port)
});
to start my server on port 8082. In server.test.js I use
var posClient = require('./pos-ClientJS.js');
to get access to the functions, that I have to test. When I run my test I get the following console output:
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't
stopped in your tests. Consider running Jest with `--
detectOpenHandles` to troubleshoot this issue.
So my question is: Is there a way to stop the server running with javascript code like stop(8082) or sth.? Or is there a less difficult way to solve this problem without stopping the process?
From the Nodejs HTTP module documentation, you can call secureServer.close() to stop listening at the specified port. If the module exposes the server to Jest, you can use the teardown methods to stop the server automatically after tests complete.
Assume that I have two files.
server.js
test.js
server.js have all the initialization codes in place (Mongoose, Express..etc). It also has the below code:
const io = require('socket.io')(server);
In my test.js file, I have something related to mqtt. It is irrelevant, however, please understand that I don't have any variable access in there (req, app). Because that file isn't part of the route or anything.
It is included in server.js as:
require('test.js');
I am not getting into any details of MQTT or how it works. Consider that one or more functions inside test.js is running on a specific time. So, when ever that happens, how can I emit an event using socket.io from the test.js file?
My client side dashboard is ready to receive the event. I am just confused how to design the system, especially how to access the io variable which exist in server.js file.
As mentioned already just export a function from test.js that takes io as a parameter:
module.exports = function test(io) {
io.on("connection", socket => {
socket.emit("greeting", "hello world!");
});
};
From your server.js you just have to pass in the argument:
require("./test.js")(io);
Please be gentle with me. I'm new to async coding and have been thrown headfirst into an intensive project using node to develop and API server. I'm loving it but some things aren't coming naturally.
Our project is built using express js. We have a file, server.js where we instantiate an express server which in turn instantiates our router and so on. I need to integration test this now (partially) complete server. Normally what I do is from the command line run '%node server.js' and then using either python requests or curl make requests and check the responses.
Now I've been tasked with writing a unit and integration test suite so that we can automate our testing going forward. I've been using mocha and now am trying to use supertest for the integration testing. The problem is that supertest expects a server object which it then applies tests to however our file that builds our server object doesn't return anything. I don't want to modify that file so I am stumped as to how to access the server object to use for testing.
My server file looks (in part) like this:
var express = require('express')
var app = express();
// Express Configuration
app.use(express.favicon()); //handles favicon request, which keeps it out of the log when using a browser :)
app.use(express.bodyParser()); //slurps up the body in chunks the node.js way :)
// ...and so on
and my mocha test file looks like this
var request = require('supertest')
, app = require('../server.js')
, assert = require("assert");
describe('POST /', function(){
it('should fail bad img_uri', function(done){
request(app)
.post('/')
.send({
'img_uri' : 'foobar'
})
.expect(500)
.end(function(err, res){
console.dir(err)
console.dir(res)
done();
})
})
})
when I run this test I get a complaint about the app object not having a method named address. My question is, is there a way I can require/call the server.js file so that the app object will be in scope? Or am I going about this wrong. I also played around a little bit with using http.js to make calls directly to the server but didn't have luck that way either. Thanks!
You need to export the app object in server.js:
var app = express();
module.exports = app;
...