Mocha API Testi: 'TypeError: app.address bir işlev değil' alınıyor


102

Benim Sorunum

Çok basit bir CRUD API kodladım ve son zamanlarda bazı testleri kullanarak da kodlamaya başladım chaive chai-httptestlerimi çalıştırırken bir sorun yaşıyorum $ mocha.

Testleri çalıştırdığımda kabukta şu hatayı alıyorum:

TypeError: app.address is not a function

Kodum

İşte testlerimden birinin bir örneği ( /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...

  });

});

Ve expressuygulama dosyalarım ( /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);
});

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

Ekstra notlar

Testleri çalıştırmadan önce /tests/server-test.js dosyasındaki serverdeğişkenin oturumunu kapatmayı denedim :

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

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

ve bunun sonucu boş bir nesnedir: server: {}.

Yanıtlar:


229

Uygulama modülünüzde hiçbir şeyi dışa aktarmazsınız. Bunu app.js dosyanıza eklemeyi deneyin:

module.exports = server

33
Bununla ilgili sahip olduğum tek sorun, uygulama kodunun asla bir teste uyacak şekilde değiştirilmemesidir.
dman

@chovy bunu çözdün mü? Aşağıda benim için çalışan bir alternatifim var.
Skyguard

1
potansiyel sorun, zaman uyumsuz hizmetler içeren sunucuyla ilgilenmektir, çünkü chai-http bunun mantığını bilmiyor ve sunucunuz tam olarak başlamadan önce bile doğrudan çalışacak
atom2ueki

1
Bu durumda sunucusunda @Nabuska muhtemelen zaten ayarlanır app.listen (...)
Garr Godfrey

Testleriniz için gerçek bir sunucuyu başlatan app.listen () kullanmamalısınız, bunun yerine http.createServer () kullanın
Whyhankee

42

Yalnızca işlev yerine http.Serverdöndürülen nesneyi dışa aktarmak önemlidir , aksi takdirde elde edersiniz .app.listen(3000)appTypeError: app.address is not a function

Misal:

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
Cevabınıza " nesneyi dışa aktarmanın neden önemli" olduğunu da eklemelisiniz http.Server.
GrumpyCrouton

@GrumpyCrouton Aksi halde alacağınız hatayı ekledim
Kim Kern

1
Teşekkür ederim Kim. Size +1 verdim çünkü bunun cevabınızı iyileştireceğini düşünüyorum. Gelecekte nedenini açıklamalısın . Birinin bu soruya baktığını ve yalnızca temel bilgiye sahip olduğunu, iyi düşünülmüş ve açıklanmış bir yanıtın onlara çok daha fazlasını öğreteceğini hayal edin.
GrumpyCrouton

Senin testler için sen sınırlandırmak değil app.listen () kullanın gerçek sunucusunu başlatan, http.createServer () yerine kullanmak
Whyhankee

28

Bu aynı zamanda yardımcı olabilir ve @dman'ın uygulama kodunu bir teste uyacak şekilde değiştirmesine yardımcı olabilir.

isteğinizi gereken şekilde localhost ve limana ilet chai.request('http://localhost:5000')

onun yerine

chai.request(server)

Bu, Koa JS (v2) ve ava js kullandığım aynı hata mesajını düzeltti.


3
Bu hatayı yaptıktan sonra gelmiyor, ancak veri alma işleminde boş geliyor ve durum kodu 200 tamam.
Anita Mehta

4

Yukarıdaki cevaplar sorunu doğru bir şekilde ele alıyor: üzerinde çalışmak supertestistiyor http.Server. Ancak, app.listen()bir sunucu almak için çağrı yapmak da bir dinleme sunucusu başlatır, bu kötü bir uygulamadır ve gereksizdir.

Bunu kullanarak dolaşabilirsiniz 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

Node + typcript serverless projemizde ts-node kullanarak mocha çalıştırdığımızda da aynı sorunu yaşadık.

Tsconfig.json dosyamızda "sourceMap" var: true. Bu şekilde oluşturulan .js ve .js.map dosyaları bazı komik çeviri sorunlarına neden olur (buna benzer). Mocha runner'ı ts-node kullanarak çalıştırdığımızda. Bu yüzden, sourceMap bayrağını false olarak ayarlayacağım ve src dizinimizdeki tüm .js ve .js.map dosyalarını sileceğim. Sonra sorun ortadan kalkar.

Src klasörünüzde zaten dosyalar oluşturduysanız, aşağıdaki komutlar gerçekten yardımcı olacaktır.

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


0

Her ihtimale karşı, birisi Hapijs kullanıyorsa, sorun hala ortaya çıkmaktadır, çünkü o Express.js kullanmamaktadır, dolayısıyla adres () işlevi mevcut değildir.

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

Çalışmasını sağlamak için geçici çözüm

// 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()
      })
    })
  })
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.