Тестування API Mocha: отримання "TypeError: app.address не є функцією"


102

Мій випуск

Я закодований дуже простий CRUD API , і я почав в останній час кодування також деякі тести з використанням chaiі , chai-httpале у мене проблема при виконанні моїх тестів з $ mocha.

Коли я запускаю тести, я отримую таку помилку на оболонці:

TypeError: app.address is not a function

Мій код

Ось зразок одного з моїх тестів ( /tests/server-test.js ):

var chai = require('chai');
var mongoose = require('mongoose');
var chaiHttp = require('chai-http');
var server = require('../server/app'); // my express app
var should = chai.should();
var testUtils = require('./test-utils');

chai.use(chaiHttp);

describe('API Tests', function() {
  before(function() {
    mongoose.createConnection('mongodb://localhost/bot-test', myOptionsObj);
  });

  beforeEach(function(done) {
    // I do stuff like populating db
  });

  afterEach(function(done) {
    // I do stuff like deleting populated db
  });

  after(function() {
    mongoose.connection.close();
  });

  describe('Boxes', function() {

    it.only('should list ALL boxes on /boxes GET', function(done) {
      chai.request(server)
        .get('/api/boxes')
        .end(function(err, res){
          res.should.have.status(200);
          done();
        });
    });

    // the rest of the tests would continue here...

  });

});

І мої expressфайли додатків ( /server/app.js ):

var mongoose = require('mongoose');
var express = require('express');
var api = require('./routes/api.js');
var app = express();

mongoose.connect('mongodb://localhost/db-dev', myOptionsObj);

// application configuration
require('./config/express')(app);

// routing set up
app.use('/api', api);

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('App listening at http://%s:%s', host, port);
});

та ( /server/routes/api.js ):

var express = require('express');
var boxController = require('../modules/box/controller');
var thingController = require('../modules/thing/controller');
var router = express.Router();

// API routing
router.get('/boxes', boxController.getAll);
// etc.

module.exports = router;

Додаткові нотатки

Я намагався вийти зі serverзмінної у файлі /tests/server-test.js перед запуском тестів:

...
var server = require('../server/app'); // my express app
...

console.log('server: ', server);
...

і я результатом цього є порожній об'єкт: server: {}.

Відповіді:


228

Ви нічого не експортуєте в модуль додатка. Спробуйте додати це у файл app.js:

module.exports = server

31
Єдине питання, що у мене є, це те, що код програми ніколи не слід змінювати, щоб він підходив до тесту.
дман

@chovy ти це вирішив? У мене є альтернатива нижче, яка працювала на мене.
Skyguard

1
потенційна проблема стосується сервера, який містить послуги асинхронізації, оскільки chai-http не знає логіки цього, і він запуститься безпосередньо до того, як ваш сервер повністю запуститься
atom2ueki

1
@Nabuska у цьому випадку сервер, мабуть, уже встановлений за допомогою app.listen (...)
Гарр Годфрі

Для своїх тестів ви не повинні використовувати app.listen (), який запускає фактичний сервер, замість цього використовуйте http.createServer ()
Whyhankee

42

Важливо експортувати http.Serverповернутий об'єкт, app.listen(3000)а не просто функцію app, інакше ви отримаєте TypeError: app.address is not a function.

Приклад:

index.js

const koa = require('koa');
const app = new koa();
module.exports = app.listen(3000);

index.spec.js

const request = require('supertest');
const app = require('./index.js');

describe('User Registration', () => {
  const agent = request.agent(app);

  it('should ...', () => {

2
Ви повинні вказати у своїй відповіді, чому "важливо експортувати http.Serverоб'єкт".
GrumpyCrouton

@GrumpyCrouton Я додав помилку, яку ви отримаєте в іншому випадку
Кім Керн

1
Дякую, Кім. Я дав вам +1, тому що я думаю, що це покращує вашу відповідь. Надалі слід пояснити, чому . Уявіть, що хтось дивиться на це питання і має лише базові знання, добре продумана і пояснена відповідь навчить їх набагато більше.
GrumpyCrouton

Для своїх тестів ви не повинні використовувати app.listen (), який запускає фактичний сервер, замість цього скористайтеся http.createServer ()
Whyhankee

28

Це також може допомогти і задовольнити @dman пункт зміни коду програми, щоб відповідати тесту.

надішліть запит до localhost та порту за потребою chai.request('http://localhost:5000')

замість

chai.request(server)

це виправлено те саме повідомлення про помилку, яке я мав за допомогою Koa JS (v2) та ava js.


3
Після цього помилка не з’являється, але в даних отримання надходить нульовий і код коду 200 ок.
Аніта Мехта

4

Наведені вище відповіді правильно вирішують питання: supertestхочеться http.Serverнад чим працювати. Однак виклик app.listen()отримати сервер також запустить прослуховуючий сервер, це погана практика і зайве.

Ви можете подолати це за допомогою http.createServer():

import * as http from 'http';
import * as supertest from 'supertest';
import * as test from 'tape';
import * as Koa from 'koa';

const app = new Koa();

# add some routes here

const apptest = supertest(http.createServer(app.callback()));

test('GET /healthcheck', (t) => {
    apptest.get('/healthcheck')
    .expect(200)
    .expect(res => {
      t.equal(res.text, 'Ok');
    })
    .end(t.end.bind(t));
});

1

У нас була така ж проблема, коли ми запускали mocha за допомогою ts-вузла в нашому проекті без сервера node + typecript.

Наш tsconfig.json мав "sourceMap": true. Таким чином, згенеровані файли .js та .js.map спричиняють деякі смішні проблеми з трансляцією (подібно до цієї). Коли ми запускаємо mocha runner за допомогою ts-вузла. Отже, я встановлю прапор sourceMap на false та видалив усі .js та .js.map файли в нашому каталозі src. Тоді питання відпадає.

Якщо ви вже створили файли у папці src, команди нижче були б дуже корисними.

знайти src-ім'я " .js.map" -exec rm {} \; знайти src -name " .js" -exec rm {} \;


0

На всякий випадок, якщо хтось використовує Hapijs, проблема все-таки виникає, оскільки він не використовує Express.js, тому функція address () не існує.

TypeError: app.address is not a function
      at serverAddress (node_modules/chai-http/lib/request.js:282:18)

Вирішення питання, щоб змусити його працювати

// this makes the server to start up
let server = require('../../server')

// pass this instead of server to avoid error
const API = 'http://localhost:3000'

describe('/GET token ', () => {
    it('JWT token', (done) => {
       chai.request(API)
         .get('/api/token?....')
         .end((err, res) => {
          res.should.have.status(200)
          res.body.should.be.a('object')
          res.body.should.have.property('token')
          done()
      })
    })
  })
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.