Pengujian API Mocha: mendapatkan 'TypeError: app.address bukan sebuah fungsi'

102

Masalah Saya

Saya telah mengkodekan CRUD API yang sangat sederhana dan saya baru-baru ini mulai mengkodekan beberapa tes juga menggunakan chaidan chai-httptetapi saya mengalami masalah saat menjalankan tes saya $ mocha.

Ketika saya menjalankan tes saya mendapatkan kesalahan berikut pada shell:

TypeError: app.address is not a function

Kode Saya

Berikut adalah contoh salah satu pengujian saya ( /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...

  });

});

Dan expressfile aplikasi saya ( /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);
});

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

Catatan ekstra

Saya telah mencoba mengeluarkan servervariabel di file /tests/server-test.js sebelum menjalankan tes:

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

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

dan saya hasil yang adalah obyek kosong: server: {}.

charliebrownie
sumber

Jawaban:

228

Anda tidak mengekspor apa pun di modul aplikasi Anda. Coba tambahkan ini ke file app.js Anda:

module.exports = server
xersiee
sumber
31
satu-satunya masalah yang saya miliki dengan ini adalah bahwa kode aplikasi tidak boleh diubah agar sesuai dengan ujian.
dman
@chovy apakah Anda menyelesaikan ini? Saya memiliki alternatif di bawah ini yang berhasil untuk saya.
Skyguard
1
masalah potensial adalah berurusan dengan server yang berisi layanan asinkron, karena chai-http tidak mengetahui logikanya, dan itu akan berjalan secara langsung bahkan sebelum server Anda sepenuhnya dimulai
atom2ueki
1
@Nabuska dalam hal ini server mungkin sudah disetel dengan app.listen (...)
Garr Godfrey
Untuk pengujian Anda, Anda tidak boleh menggunakan app.listen () yang memulai server sebenarnya, gunakan http.createServer () sebagai gantinya
Whyhankee
42

Penting untuk mengekspor http.Serverobjek yang dikembalikan, app.listen(3000)bukan hanya fungsi app, jika tidak, Anda akan mendapatkannya TypeError: app.address is not a function.

Contoh:

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
sumber
2
Anda harus memasukkan dalam jawaban Anda mengapa "penting untuk mengekspor http.Serverobjek".
GrumpyCrouton
@GrumpyCrouton Saya menambahkan kesalahan yang akan Anda dapatkan sebaliknya
Kim Kern
1
Terima kasih Kim. Saya memberi Anda +1 karena menurut saya hal itu meningkatkan jawaban Anda. Di masa depan, Anda harus menjelaskan alasannya . Bayangkan seseorang melihat pertanyaan ini dan hanya memiliki pengetahuan dasar, jawaban yang dipikirkan dengan matang dan dijelaskan akan mengajari mereka lebih banyak.
GrumpyCrouton
Untuk pengujian Anda, Anda tidak boleh menggunakan app.listen () yang memulai server sebenarnya, gunakan http.createServer () sebagai gantinya
Whyhankee
28

Ini juga dapat membantu, dan memenuhi poin @dman untuk mengubah kode aplikasi agar sesuai dengan pengujian.

buat permintaan Anda ke localhost dan port sesuai kebutuhan chai.request('http://localhost:5000')

dari pada

chai.request(server)

ini memperbaiki pesan kesalahan yang sama saya menggunakan Koa JS (v2) dan ava js.

Skyguard
sumber
3
Setelah melakukan kesalahan ini tidak datang, tetapi di dapatkan data menjadi null dan kode status 200 ok.
Anita Mehta
4

Jawaban di atas dengan benar mengatasi masalah: supertestingin http.Serverdikerjakan. Namun, memanggil app.listen()untuk mendapatkan server juga akan memulai server pendengar, ini adalah praktik yang buruk dan tidak perlu.

Anda dapat menyiasatinya dengan menggunakan 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
sumber
1

Kami memiliki masalah yang sama ketika kami menjalankan mocha menggunakan ts-node di proyek tanpa server node + skrip.

Tsconfig.json kita memiliki "sourceMap": true. Jadi, file .js dan .js.map yang dihasilkan menyebabkan beberapa masalah transpiling yang lucu (mirip dengan ini). Saat kami menjalankan mocha runner menggunakan ts-node. Jadi, saya akan menyetel flag sourceMap ke false dan menghapus semua file .js dan .js.map di direktori src kami. Kemudian masalahnya hilang.

Jika Anda telah membuat file di folder src Anda, perintah di bawah ini akan sangat membantu.

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

Dilunika
sumber
0

Untuk berjaga-jaga, jika seseorang menggunakan Hapijs, masalah masih terjadi, karena tidak menggunakan Express.js, sehingga fungsi address () tidak ada.

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

Solusi untuk membuatnya berhasil

// 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
sumber