Javascript 可以在我的Jest测试套件中创建Express.js服务器吗?

Javascript 可以在我的Jest测试套件中创建Express.js服务器吗?,javascript,node.js,unit-testing,express,jestjs,Javascript,Node.js,Unit Testing,Express,Jestjs,我正在尝试测试一个函数,该函数使用axios从外部API获取数据。为了使我的测试函数尽可能接近真实的东西,我正在查询文件中的模拟数据。Axios无法从本地文件返回数据,这是一项安全功能。所以我尝试的解决方案是在我的测试套件中启动一个简单的服务器,在那里提供文件,然后运行我的测试 我的测试套件现在看起来像这样: import React from 'react'; import {shallow} from 'enzyme'; import express from 'express'; impo

我正在尝试测试一个函数,该函数使用axios从外部API获取数据。为了使我的测试函数尽可能接近真实的东西,我正在查询文件中的模拟数据。Axios无法从本地文件返回数据,这是一项安全功能。所以我尝试的解决方案是在我的测试套件中启动一个简单的服务器,在那里提供文件,然后运行我的测试

我的测试套件现在看起来像这样:

import React from 'react';
import {shallow} from 'enzyme';
import express from 'express';
import { getFeedId, getFeedData, reverseStop } from '../mocks/apiMock';

const app = express();
const port = 4000;
app.use(express.static('../mocks/MockData.json'));
app.listen(port, tests());

function tests () {
    it('returns the expected feed id for a given subway line', () => {
        expect(getFeedId('L')).toBe(2);
    });

    it('returns json data', () => {
        expect.assertions(2);
        return getFeedData('L').then(data => {
            expect(data).toBeDefined();
            expect(data.header.gtfs_realtime_version).toBe('1.0');
        });
    });

    it('returns a stop_id for a given subway line and stop', () => {
        expect(reverseStop('L', 'Lorimer St')).toBe('L10N');
    });
}
我正在测试的函数是这样的(使用Axios的函数是getFeedData,所以我认为其他函数没有引起问题,但我不是肯定的)


我对这个问题的最佳猜测是,也许Jest不会在节点环境中运行(有什么方法可以解决这个问题吗)?因此,可能Express服务器根本没有运行。然而,我有点超出我的专业知识,所以这只是一个猜测。有人能解释一下到底发生了什么吗?我运行Express服务器的想法好吗?把它放在测试套件中是个好主意吗?如果其中一个或两个问题的答案都是“否”,那么这里的最佳做法是什么?

您应该在每个()之前创建服务器(并在每个()之后停止服务器),以便它在每个测试中运行


您还应该选择一个未使用的端口,以便测试可以并行运行。

为了避免所有源文件之间的代码重复,您可以创建一个节点环境,该环境将为所有测试文件设置:

package.json

{
“名称”:“我的项目”,
“笑话”:{
“TestenEnvironment”:“/testenEnvironment.js”
}
}
testEnvironment.js

const express=require('express');
//用于服务器节点应用程序
//const NodeEnvironment=require('jest-environment-node');
//用于浏览器js应用程序
const NodeEnvironment=require('jest-environment-jsdom');
类ExpressEnvironment扩展了NodeEnvironment{
构造函数(配置,上下文){
超级(配置,上下文);
}
异步设置(){
等待super.setup();
让服务器;
常量app=express();
等待新承诺(功能(解决){
服务器=app.listen(0,“127.0.0.1”,函数(){
让address=server.address();
console.log(
`在“${JSON.stringify(address)}”上运行服务器…`);
解决();
});
});
让address=server.address();
this.global.server=服务器;
this.global.address=`${address.address}:${address.port}`
app.use(express.static('./testfiles');
}
异步拆卸(){
this.global.server.close();
等待super.teardown();
}
运行脚本(脚本){
返回super.runScript(script);
}
}
module.exports=ExpressEnvironment;
然后,您可以访问测试文件中的
this.global.server
,以获取服务器端口/地址:

test.js

test('Show the server address as example',()=>{
//@ts忽略:https://github.com/kulshekhar/ts-jest/issues/1533
让address=global.address;
log(`服务器地址是'${address}'…`)
});
结果:

$ npx jest
 PASS  src/reviewer.test.ts (5.391s)
  √ renders GitHub Repository Researcher site name (10ms)

Running server on '{"address":"127.0.0.1","family":"IPv4","port":50875}'.
  console.log src/reviewer.test.ts:25
    The server address is '127.0.0.1:50875'.

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        6.811s
Ran all test suites.
请记住文档警告:

注意:测试环境是沙盒。每个测试套件/文件将在各自的测试环境中触发设置/拆卸


或者,您可以将
globalSetup
globalTeardown
testEnvironment

package.json

{
“名称”:“我的项目”,
“笑话”:{
“TestenEnvironment”:“/testenEnvironment.js”,
“globalSetup”:“/globalSetup.js”,
“globalTeardown”:“/globalTeardown.js”
}
}
globalTeardown.js

module.exports=async()=>{
global.server.close();
};
globalSetup.js

const express=require('express');
module.exports=async()=>{
让服务器;
常量app=express();
等待新承诺(功能(解决){
服务器=app.listen(0,“127.0.0.1”,函数(){
让address=server.address();
log(`Running express on'${JSON.stringify(address)}'…`);
解决();
});
});
let address=server.address()
global.server=服务器;
process.env.SERVER_ADDRESS=`http://${ADDRESS.ADDRESS}:${ADDRESS.port}`
app.use(express.static('./testfiles');
};
testEnvironment.js

const TestEnvironment=require('jest-environment-jsdom');//用于浏览器js应用程序
//const TestEnvironment=require('jest-environment-node');//用于服务器节点应用程序
类ExpressEnvironment扩展了TestenEnvironment{
构造函数(配置,上下文){
让cloneconfig=Object.assign({},config)
cloneconfig.testURL=process.env.SERVER\u地址;
super(cloneconfig,context);
}
异步设置(){
this.global.jsdom=this.dom;
等待super.setup();
}
异步拆卸(){
this.global.jsdom=null;
等待super.teardown();
}
运行脚本(脚本){
返回super.runScript(script);
}
}
module.exports=ExpressEnvironment;

如果它没有在节点中运行,Express本身将给出错误。旁注:您实际上并没有将回调传递给
listen()
。传递一个可能会解决你的问题。我不是通过回调来听吗?我认为通过
tests()
作为第二个参数是我的回调。另外,您还可以在下面说,使beforeach()异步并将回调传递给
listen()
listen();您正在调用
tests()
并传递其返回值(即
未定义的
)。就像任何其他函数调用一样。您应该调用
listen()FAIL  src/tests/api.test.js (23.311s)
  ● returns json data

Network Error

  at createError (node_modules/axios/lib/core/createError.js:16:15)
  at XMLHttpRequest.handleError [as onerror] (node_modules/axios/lib/adapters/xhr.js:87:14)
  at XMLHttpRequest.callback.(anonymous function) (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:289:32)
  at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27)
  at invokeInlineListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:166:7)
  at EventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:122:7)
  at EventTargetImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17)
  at XMLHttpRequest.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35)
  at dispatchError (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:994:9)
  at validCORSHeaders (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:1009:7)
  at receiveResponse (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:871:12)
  at Request.client.on.res (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:691:38)
  at emitOne (events.js:96:13)
  at Request.emit (events.js:191:7)
  at Request.onRequestResponse (node_modules/request/request.js:1074:10)
  at emitOne (events.js:96:13)
  at ClientRequest.emit (events.js:191:7)
  at HTTPParser.parserOnIncomingClient (_http_client.js:522:21)
  at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)
  at Socket.socketOnData (_http_client.js:411:20)
  at emitOne (events.js:96:13)
  at Socket.emit (events.js:191:7)
  at readableAddChunk (_stream_readable.js:178:18)
  at Socket.Readable.push (_stream_readable.js:136:10)
  at TCP.onread (net.js:560:20)

  ● returns json data

expect.assertions(2)

Expected two assertions to be called but only received zero assertion calls.

  at addAssertionErrors (node_modules/jest-jasmine2/build/setup-jest-globals.js:68:21)
  at process._tickCallback (internal/process/next_tick.js:109:7)```
$ npx jest
 PASS  src/reviewer.test.ts (5.391s)
  √ renders GitHub Repository Researcher site name (10ms)

Running server on '{"address":"127.0.0.1","family":"IPv4","port":50875}'.
  console.log src/reviewer.test.ts:25
    The server address is '127.0.0.1:50875'.

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        6.811s
Ran all test suites.