TypeError: _app.app.close is not a function using jest 27.5.1
TypeError: _app.app.close is not a function using jest 27.5.1
我有一个测试在 Jest 27.5.1 上失败(babel-jest 在同一版本)并出现此错误
我在使用 Jest 26.6.3 时没有收到此错误(babel-jest 也在 26.6.3)
我的测试文件
import supertest from 'supertest';
import {
buildAccount,
buildAuthenticationType,
createAccount,
createAuthenticationType,
} from './factories';
import {
startDatabase,
ENDPOINT_PREFIX,
clearDatabase,
doLogin,
} from './utils';
import { Account, AuthenticationType } from 'data/models';
import { app } from 'server/app';
const agent = supertest.agent(app);
const ENDPOINT = `${ENDPOINT_PREFIX}/account`;
describe('Account tests', () => {
beforeEach(async () => {
await startDatabase();
await doLogin(agent);
});
afterAll(async () => {
await clearDatabase();
console.log(typeof app.close, app.close);
await app.close();
});
test('/POST - Response with a new created account', async () => {
const relAuthenticationTypeIdDict = await buildAuthenticationType({});
const relFakeAuthenticationTypeId = await createAuthenticationType(
relAuthenticationTypeIdDict
);
const fakeAccount = await buildAccount({
authenticationTypeId: relFakeAuthenticationTypeId.authenticationTypeId,
});
const response = await agent.post(ENDPOINT).send(fakeAccount);
expect(response.status).toBe(201);
expect(response.statusCode).toBe(201);
const responseAccount = response.body.data;
const account = await Account.findByPk(responseAccount.accountId);
expect(account.email).toBe(fakeAccount.email);
expect(account.emailVerified).toBe(fakeAccount.emailVerified);
expect(account.isPrimary).toBe(fakeAccount.isPrimary);
expect(account.username).toBe(fakeAccount.username);
expect(account.password).toBe(undefined);
expect(account.pictureUrl).toBe(fakeAccount.pictureUrl);
expect(account.socialAccountId).toBe(fakeAccount.socialAccountId);
expect(account.authenticationTypeId).toBe(fakeAccount.authenticationTypeId);
});
});
我的app.js文件
import express from 'express';
import path from 'path';
import logger from 'morgan';
import passport from 'passport';
import swaggerUi from 'swagger-ui-express';
import { adminbroRouter } from './routes/adminbro.route';
import { router } from './routes';
import { sessionParser } from './session';
import { swaggerDocument } from './swagger';
import {
errorHandler,
responseHandler,
pageNotFoundHandler,
initResLocalsHandler,
} from './middlewares';
import { refreshFeedItemTagsQueue } from 'jobs/refresh-feed-item-tags';
import { ACCEPTED, NOT_FOUND, OK } from 'http-status';
import './passport';
const app = express();
// Swagger
app.use(
'/swagger',
swaggerUi.serveFiles(swaggerDocument),
swaggerUi.setup(swaggerDocument)
);
// Middlewares
app.use(logger('dev'));
app.use('/admin', adminbroRouter);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(sessionParser);
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use(initResLocalsHandler);
app.use(process.env.BASE_PATH, router);
// Use custom response handler
app.use(responseHandler);
// Use custom error handler
app.use(errorHandler);
// Page not found
app.use(pageNotFoundHandler);
export { app };
我的server.js文件
// eslint-disable-next-line import/first
import http from 'http';
import { app } from './app';
import { sessionParser } from './session';
import { websocketServer } from './ws';
import 'jobs/repeatable';
const server = http.createServer(app);
server.on('upgrade', (request, socket, head) => {
sessionParser(request, {}, () => {
websocketServer.handleUpgrade(request, socket, head, (ws) => {
websocketServer.emit('connection', ws, request);
});
});
});
/* istanbul ignore next */
const PORT = process.env.PORT || 8000;
/* istanbul ignore next */
server.listen(PORT, () => {
// eslint-disable-next-line no-console
console.log(`Express server listening on port ${PORT}`);
});
怎么可能旧版本的 jest 没有出现这个错误而新版本出现了?
app
由 express()
创建,没有 close
方法。但是const server = http.createServer(app);
,server
有一个close
方法。
您可以启动服务器并监听 beforeAll
中的连接并在 afterAll
中调用 server.close
。为此,您需要导出 server
以便测试文件可以获得 server
.
if (require.main === module)
块中的语句只有在 运行 此脚本被 node server.js
时才会执行。
例如
app.ts
import express from 'express';
const app = express();
app.get('/heartbeat', (req, res) => {
res.sendStatus(200);
});
export { app };
server.ts
:
import http from 'http';
import { app } from './app';
const server = http.createServer(app);
const PORT = process.env.PORT || 8000;
if (require.main === module) {
server.listen(PORT, () => {
console.log(`Express server listening on port ${PORT}`);
});
}
export { server };
server.test.ts
:
import supertest from 'supertest';
import { app } from './app';
import { server } from './server';
const agent = supertest.agent(app);
describe('server', () => {
before((done) => {
server.listen(7890, () => {
console.log('Test server listening on port: 7890');
done();
});
});
after((done) => {
server.close(done);
});
it('should pass', () => {
return agent.get('/heartbeat').expect(200);
});
});
测试结果:
server
Test server listening on port: 7890
✓ should pass
1 passing (20ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 84.62 | 75 | 50 | 84.62 |
app.ts | 100 | 100 | 100 | 100 |
server.ts | 75 | 75 | 0 | 75 | 9-10
-----------|---------|----------|---------|---------|-------------------
我有一个测试在 Jest 27.5.1 上失败(babel-jest 在同一版本)并出现此错误
我在使用 Jest 26.6.3 时没有收到此错误(babel-jest 也在 26.6.3) 我的测试文件
import supertest from 'supertest';
import {
buildAccount,
buildAuthenticationType,
createAccount,
createAuthenticationType,
} from './factories';
import {
startDatabase,
ENDPOINT_PREFIX,
clearDatabase,
doLogin,
} from './utils';
import { Account, AuthenticationType } from 'data/models';
import { app } from 'server/app';
const agent = supertest.agent(app);
const ENDPOINT = `${ENDPOINT_PREFIX}/account`;
describe('Account tests', () => {
beforeEach(async () => {
await startDatabase();
await doLogin(agent);
});
afterAll(async () => {
await clearDatabase();
console.log(typeof app.close, app.close);
await app.close();
});
test('/POST - Response with a new created account', async () => {
const relAuthenticationTypeIdDict = await buildAuthenticationType({});
const relFakeAuthenticationTypeId = await createAuthenticationType(
relAuthenticationTypeIdDict
);
const fakeAccount = await buildAccount({
authenticationTypeId: relFakeAuthenticationTypeId.authenticationTypeId,
});
const response = await agent.post(ENDPOINT).send(fakeAccount);
expect(response.status).toBe(201);
expect(response.statusCode).toBe(201);
const responseAccount = response.body.data;
const account = await Account.findByPk(responseAccount.accountId);
expect(account.email).toBe(fakeAccount.email);
expect(account.emailVerified).toBe(fakeAccount.emailVerified);
expect(account.isPrimary).toBe(fakeAccount.isPrimary);
expect(account.username).toBe(fakeAccount.username);
expect(account.password).toBe(undefined);
expect(account.pictureUrl).toBe(fakeAccount.pictureUrl);
expect(account.socialAccountId).toBe(fakeAccount.socialAccountId);
expect(account.authenticationTypeId).toBe(fakeAccount.authenticationTypeId);
});
});
我的app.js文件
import express from 'express';
import path from 'path';
import logger from 'morgan';
import passport from 'passport';
import swaggerUi from 'swagger-ui-express';
import { adminbroRouter } from './routes/adminbro.route';
import { router } from './routes';
import { sessionParser } from './session';
import { swaggerDocument } from './swagger';
import {
errorHandler,
responseHandler,
pageNotFoundHandler,
initResLocalsHandler,
} from './middlewares';
import { refreshFeedItemTagsQueue } from 'jobs/refresh-feed-item-tags';
import { ACCEPTED, NOT_FOUND, OK } from 'http-status';
import './passport';
const app = express();
// Swagger
app.use(
'/swagger',
swaggerUi.serveFiles(swaggerDocument),
swaggerUi.setup(swaggerDocument)
);
// Middlewares
app.use(logger('dev'));
app.use('/admin', adminbroRouter);
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(sessionParser);
app.use(passport.initialize());
app.use(passport.session());
app.use(express.static(path.join(__dirname, 'public')));
app.use(initResLocalsHandler);
app.use(process.env.BASE_PATH, router);
// Use custom response handler
app.use(responseHandler);
// Use custom error handler
app.use(errorHandler);
// Page not found
app.use(pageNotFoundHandler);
export { app };
我的server.js文件
// eslint-disable-next-line import/first
import http from 'http';
import { app } from './app';
import { sessionParser } from './session';
import { websocketServer } from './ws';
import 'jobs/repeatable';
const server = http.createServer(app);
server.on('upgrade', (request, socket, head) => {
sessionParser(request, {}, () => {
websocketServer.handleUpgrade(request, socket, head, (ws) => {
websocketServer.emit('connection', ws, request);
});
});
});
/* istanbul ignore next */
const PORT = process.env.PORT || 8000;
/* istanbul ignore next */
server.listen(PORT, () => {
// eslint-disable-next-line no-console
console.log(`Express server listening on port ${PORT}`);
});
怎么可能旧版本的 jest 没有出现这个错误而新版本出现了?
app
由 express()
创建,没有 close
方法。但是const server = http.createServer(app);
,server
有一个close
方法。
您可以启动服务器并监听 beforeAll
中的连接并在 afterAll
中调用 server.close
。为此,您需要导出 server
以便测试文件可以获得 server
.
if (require.main === module)
块中的语句只有在 运行 此脚本被 node server.js
时才会执行。
例如
app.ts
import express from 'express';
const app = express();
app.get('/heartbeat', (req, res) => {
res.sendStatus(200);
});
export { app };
server.ts
:
import http from 'http';
import { app } from './app';
const server = http.createServer(app);
const PORT = process.env.PORT || 8000;
if (require.main === module) {
server.listen(PORT, () => {
console.log(`Express server listening on port ${PORT}`);
});
}
export { server };
server.test.ts
:
import supertest from 'supertest';
import { app } from './app';
import { server } from './server';
const agent = supertest.agent(app);
describe('server', () => {
before((done) => {
server.listen(7890, () => {
console.log('Test server listening on port: 7890');
done();
});
});
after((done) => {
server.close(done);
});
it('should pass', () => {
return agent.get('/heartbeat').expect(200);
});
});
测试结果:
server
Test server listening on port: 7890
✓ should pass
1 passing (20ms)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 84.62 | 75 | 50 | 84.62 |
app.ts | 100 | 100 | 100 | 100 |
server.ts | 75 | 75 | 0 | 75 | 9-10
-----------|---------|----------|---------|---------|-------------------