如何正确使用Jest对Express 4服务器进行单元测试

kninwzqo  于 8个月前  发布在  Jest
关注(0)|答案(2)|浏览(105)

为了更好地理解它,我测试了这个简单的Express服务器(v4)设置代码:

server.js

import express from 'express';
    import router from './routes';

    const app = express();
    app.use(router);

    const server = app.listen(3000, function () {
      var port = this.address().port;
      /* eslint-disable no-console */
      console.log('Example app listening on port %s!', port);
    });

    export default app; // as suggested by Ron

字符串
使用以下路由器

routes.js

var express = require('express');
    var defaultController = require('./controllers/defaultController');

    var router = express.Router();

    router.get('/', defaultController.getHome);

    module.exports = router;


它的清洁(eslinted)和运行良好的Yarn开始
我写了(从tuts复制/粘贴..写于2015年)以下规范来测试server.js与Jest和SuperTest

server.spec.js

var request = require('supertest');

    describe('loading express', function () {
        var server; // http server object

        beforeEach(function () {
            delete require.cache[require.resolve('../src/server')];
            server = require('../src/server');
        });

        afterEach(function () {
            server.close();
        });

        it('responds to /', function testSlash(done) {
            request(server)
              .get('/')
              .expect(200, done);
        });

        it('404 everything else', function testPath(done) {
            request(server)
              .get('/foo/bar')
              .expect(404, done);
        });
    });


但它失败了...在.get()上出现类型错误。
类型错误:app.address不是函数
server.close()上的类型错误
类型错误:server.close不是函数
这里是完整的console.log

$Yarn测试

yarn run v1.9.4
        $ jest --runInBand --verbose
         FAIL  test/server.spec.js
          loading express
            ✕ responds to / (275ms)
            ✕ 404 everything else (1ms)

          ● loading express › responds to /

            TypeError: app.address is not a function

              16 |     it('responds to /', function testSlash(done) {
              17 |         request(server)
            > 18 |           .get('/')
                 |            ^
              19 |           .expect(200, done);
              20 |     });
              21 |

              at Test.Object.<anonymous>.Test.serverAddress (node_modules/supertest/lib/test.js:55:18)
              at new Test (node_modules/supertest/lib/test.js:36:12)
              at Object.obj.(anonymous function) [as get] (node_modules/supertest/index.js:25:14)
              at Object.get (test/server.spec.js:18:12)

          ● loading express › responds to /

            TypeError: server.close is not a function

              11 |
              12 |     afterEach(function () {
            > 13 |         server.close();
                 |                ^
              14 |     });
              15 |
              16 |     it('responds to /', function testSlash(done) {

              at Object.close (test/server.spec.js:13:16)

          ● loading express › 404 everything else

            TypeError: app.address is not a function

              22 |     it('404 everything else', function testPath(done) {
              23 |         request(server)
            > 24 |           .get('/foo/bar')
                 |            ^
              25 |           .expect(404, done);
              26 |     });
              27 | });

              at Test.Object.<anonymous>.Test.serverAddress (node_modules/supertest/lib/test.js:55:18)
              at new Test (node_modules/supertest/lib/test.js:36:12)
              at Object.obj.(anonymous function) [as get] (node_modules/supertest/index.js:25:14)
              at Object.get (test/server.spec.js:24:12)

          ● loading express › 404 everything else

            TypeError: server.close is not a function

              11 |
              12 |     afterEach(function () {
            > 13 |         server.close();
                 |                ^
              14 |     });
              15 |
              16 |     it('responds to /', function testSlash(done) {

              at Object.close (test/server.spec.js:13:16)

          console.log src/server.js:11
            Example app listening on port 3000!

        Test Suites: 1 failed, 1 total
        Tests:       2 failed, 2 total
        Snapshots:   0 total
        Time:        1.062s
        Ran all test suites.
        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.

xdyibdwo

xdyibdwo1#

对于错误:
类型错误:app.address不是函数

类型错误:server.close不是函数
变化

var server;
beforeEach(function() {
  delete require.cache[require.resolve('./server')];
  server = require('./server');
});

字符串
收件人:

var server;

beforeEach(function() {
  delete require.cache[require.resolve('./server')];
  server = require('./server').default;
});


由于您在server.js文件中启动HTTP服务器,这意味着当您在测试文件中执行require('./server')语句时,服务器将启动。您应该在所有测试完成后关闭服务器。否则,它将抛出错误:
错误[ERR_SERVER_NOT_RUNNING]:服务器未运行。
变化

afterEach(function(done) {
  server.close(done);
});


收件人:

afterAll(function(done) {
  server.close(done);
});


express创建的app对象没有.close()方法,但http.server有。
变更:

const server = app.listen(3000, function() {
  var port = this.address().port;
  console.log('Example app listening on port %s!', port);
});

export default app;


收件人:

const server = app.listen(3000, function() {
  var port = this.address().port;
  console.log('Example app listening on port %s!', port);
});

export default server;


100%覆盖率的集成测试结果:

☁  jest-codelab [master] ⚡  npx jest --coverage --verbose /Users/ldu020/workspace/github.com/mrdulin/jest-codelab/src/stackoverflow/53920812/server.spec.js
 PASS  src/stackoverflow/53920812/server.spec.js
  loading express
    ✓ responds to / (741ms)
    ✓ 404 everything else (6ms)

  console.log src/stackoverflow/53920812/server.js:428
    Example app listening on port 3000!

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 routes.js |      100 |      100 |      100 |      100 |                   |
 server.js |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.865s, estimated 10s


源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/53920812

cgyqldqp

cgyqldqp2#

Supertest不是在寻找服务器,而是在寻找应用程序。然后它会获取该应用程序并运行自己的服务器进行测试。将server.js文件分为两个文件:
app.js

import express from 'express';
import router from './routes';

const app = express();
app.use(router);

const server = app.listen(3000, function () {
  var port = this.address().port;
  /* eslint-disable no-console */
  console.log('Example app listening on port %s!', port);
});

export default app;

字符串
server.js

import app from './app';

const server = app.listen(3000, function () {
  var port = this.address().port;
  /* eslint-disable no-console */
  console.log('Example app listening on port %s!', port);
});

export default server;


然后你可以把你的测试改成这样:

var request = require('supertest');

describe('loading express', function () {
    const app = require('../app'); // Or whereever your app is

    it('responds to /', function testSlash(done) {
        request(app)
          .get('/')
          .expect(200, done);
    });

    it('404 everything else', function testPath(done) {
        request(app)
          .get('/foo/bar')
          .expect(404, done);
    });
});


因为Supertest运行的是它自己的示例,所以您不必每次都关闭另一个竞争服务器。现在,当您准备进入生产模式时,只需运行node server

相关问题