Mokka-API-Test: Abrufen von 'TypeError: app.address ist keine Funktion'

101

Mein Problem

Ich habe eine sehr einfache CRUD API codiert , und ich habe vor kurzem Codierung auch einige Tests begann mit chaiund chai-httpaber ich bin ein Problem, wenn sie mit meinen Tests laufen $ mocha.

Wenn ich die Tests ausführe, wird der folgende Fehler in der Shell angezeigt:

TypeError: app.address is not a function

Mein Code

Hier ist ein Beispiel eines meiner Tests ( /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...

  });

});

Und meine expressApp-Dateien ( /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);
});

und ( /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;

Zusätzliche Hinweise

Ich habe versucht, die serverVariable in der Datei /tests/server-test.js abzumelden , bevor ich die Tests ausführte :

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

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

und ich das Ergebnis davon ist ein leeres Objekt : server: {}.

Charliebrownie
quelle

Antworten:

228

Sie exportieren nichts in Ihr App-Modul. Versuchen Sie, dies zu Ihrer app.js-Datei hinzuzufügen:

module.exports = server
xersiee
quelle
31
Das einzige Problem, das ich dabei habe, ist, dass der Anwendungscode niemals geändert werden sollte, um einem Test zu entsprechen.
Dman
@chovy hast du das gelöst? Ich habe unten eine Alternative, die für mich funktioniert hat.
Skyguard
1
Das potenzielle Problem besteht darin, sich mit einem Server zu befassen, der asynchrone Dienste enthält, da chai-http die Logik dafür nicht kennt und direkt ausgeführt wird, noch bevor Ihr Server vollständig gestartet wurde
atom2ueki
1
@Nabuska in diesem Fall Server ist wahrscheinlich bereits mit app.listen (...) eingestellt
Garr Godfrey
Für Ihre Tests sollten Sie nicht app.listen () verwenden, das einen tatsächlichen Server startet, sondern stattdessen http.createServer ()
Whyhankee
42

Es ist wichtig, das zurückgegebene http.ServerObjekt app.listen(3000)anstatt nur der Funktion zu exportieren app, da Sie sonst erhalten TypeError: app.address is not a function.

Beispiel:

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 ...', () => {
Kim Kern
quelle
2
Sie sollten in Ihre Antwort aufnehmen, warum es "wichtig ist, das http.ServerObjekt zu exportieren ".
GrumpyCrouton
@GrumpyCrouton Ich habe den Fehler hinzugefügt, den Sie sonst erhalten
Kim Kern
1
Danke Kim. Ich habe dir eine +1 gegeben, weil ich denke, dass das deine Antwort verbessert. In Zukunft sollten Sie erklären, warum . Stellen Sie sich vor, jemand, der sich diese Frage ansieht und nur über Grundkenntnisse verfügt. Eine gut durchdachte und erklärte Antwort bringt ihm viel mehr bei.
GrumpyCrouton
Für Ihre Tests sollten Sie nicht app.listen () verwenden, das einen tatsächlichen Server startet. Verwenden Sie stattdessen http.createServer ()
Whyhankee
28

Dies kann ebenfalls hilfreich sein und erfüllt den @ dman-Punkt, den Anwendungscode an einen Test anzupassen.

Stellen Sie Ihre Anfrage nach Bedarf an den lokalen Host und den Port chai.request('http://localhost:5000')

anstatt

chai.request(server)

Dies behebt die gleiche Fehlermeldung, die ich bei der Verwendung von Koa JS (v2) und ava js hatte.

Skyguard
quelle
3
Danach kommt dieser Fehler nicht, aber in get werden die Daten null und der Statuscode 200 ok.
Anita Mehta
4

Die obigen Antworten sprechen das Problem richtig an: Sie supertestmöchten http.Serverdaran arbeiten. Wenn Sie jedoch anrufen app.listen(), um einen Server zu erhalten, wird auch ein Listening-Server gestartet. Dies ist eine schlechte Praxis und nicht erforderlich.

Sie können dies umgehen, indem Sie Folgendes verwenden 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));
});
Whyhankee
quelle
1

Wir hatten das gleiche Problem, als wir Mokka mit ts-node in unserem serverlosen Projekt node + typescript ausführen.

Unsere tsconfig.json hatte "sourceMap": true. So generierte .js- und .js.map-Dateien verursachen einige lustige Transpiling-Probleme (ähnlich wie diese). Wenn wir Mokka Runner mit ts-node ausführen. Also werde ich das Flag sourceMap auf false setzen und alle .js- und .js.map-Dateien in unserem src-Verzeichnis löschen. Dann ist das Problem weg.

Wenn Sie bereits Dateien in Ihrem src-Ordner generiert haben, sind die folgenden Befehle sehr hilfreich.

find src -name " .js.map" -exec rm {} \; find src -name " .js" -exec rm {} \;

Dilunika
quelle
0

Nur für den Fall, dass jemand Hapijs verwendet, tritt das Problem weiterhin auf, da Express.js nicht verwendet wird, sodass die Funktion address () nicht vorhanden ist.

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

Die Problemumgehung, damit es funktioniert

// 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()
      })
    })
  })
Leonardo Ampuero
quelle