#unit-testing #testing #jestjs
#модульное тестирование #тестирование #jestjs
Вопрос:
Я написал тестовые примеры для signin API с использованием jest. После завершения всех пяти тестов тестового костюма jest выдает мне следующую ошибку в журнале.
Может ли кто-нибудь объяснить, почему это так и как это исправить?
КОД: (signup.test.ts)
import request from 'supertest';
import { TYPES } from '../src/inversify.types'
import { Application } from '../src/app/Application'
import { container } from '../src/inversify.config'
import dotenv from 'dotenv'
import { RESPONSE_CODE } from '../src/utils/enums/ResponseCode'
import { RESPONSE_MESSAGES } from '../src/utils/enums/ResponseMessages'
import { UserSchema } from '../src/components/user/User';
// import jwt from 'jsonwebtoken';
var application: Application
describe("POST / - SIGNUP endpoint", () => {
// var testusers: any;
//This hook is executed before running all test cases, It will make application instance, make it to listen
// on it on port 3000 and add test document in DB
beforeAll(async () => {
// Make enviroment variables available throughout the application
dotenv.config();
// Getting application instance using iversify container
application = container.get<Application>(TYPES.Application);
// Initialize frontside of application
await application.bootstrap();
// Starting Application server on given port
await application.listen(3000);
});
afterAll(
//This hook is executed after running all test cases and delete test document in database
async () =>{
const res = await UserSchema.deleteMany({ Name: { $in: [ "Test User", "Test" ] } });
// `0` if no docs matched the filter, number of docs deleted otherwise
console.log('---------------------->>>>>>>>>>>>>>>>>>>', (res as any).deletedCount);
}
)
it("Signup for user that don't exists", async () => {
const response = await request(application.getServer()).post('/user/signup')
.send({
"Email": JSON.parse(process.env.TEST_USER).Email,
"Name": "Test User",
"Password": process.env.TEST_ACCOUNTS_PASSWORD
})
expect(response.status).toBe(RESPONSE_CODE.CREATED);
expect(JSON.parse(response.text)).toEqual(expect.objectContaining({
Message: RESPONSE_MESSAGES.ADDED_SUCESSFULLY,
Data: expect.objectContaining({
Name: 'Test User',
Country: '',
PhoneNumber: '',
// Password: '$2b$10$nIHLW/SA73XLHoIcND27iuODFAArOvpch6FL/eikKT78qbShAl6ry',
Dob: '',
Role: 'MEMBER',
IsEmailVerified: false,
IsBlocked: 'ACTIVE',
IsTokenSent: false,
twoFAStatus: false,
// _id: '5c812e2715e0711b98260fee',
Email: JSON.parse(process.env.TEST_USER).Email
})
})
);
console.log('*** Signup for user that don't exists *** response', response.text, 'response status', response.status);
});
it("Signup for user that exists", async () => {
const response = await request(application.getServer()).post('/user/signup')
.send({
"Email": JSON.parse(process.env.TEST_USER).Email,
"Name": "Test User",
"Password": process.env.TEST_ACCOUNTS_PASSWORD
})
expect(response.status).toBe(RESPONSE_CODE.CONFLICT);
expect(JSON.parse(response.text)).toEqual({
Message: RESPONSE_MESSAGES.ALREADY_EXISTS
})
console.log('*** Signup for user that don't exists *** response', response.text, 'response status', response.status);
});
});
Jest не вышел через секунду после завершения тестового запуска.
Обычно это означает, что существуют асинхронные операции, которые не были остановлены в ваших тестах. Рассмотрите возможность запуска Jest с
--detectOpenHandles
для устранения этой проблемы.Не удается войти в систему после выполнения тестов. Вы забыли дождаться чего-то асинхронного в вашем тесте?
Attempted to log "{ accepted: [ 'unverifiedtestuser@abc.com' ],
rejected: [],
envelopeTime: 621,
messageTime: 867,
messageSize: 906,
response: '250 2.0.0 OK 1551945300 f6sm5442066wrt.87 - gsmtp',
envelope:
{ from: 'abc@gmail.com',
to: [ 'unverifiedtestuser@abc.com' ] },
messageId: '<45468449-b5c8-0d86-9404-d55bb5f4g6a3@gmail.com>' }".
at CustomConsole.log (node_modules/jest-util/build/CustomConsole.js:156:10)
at src/email/MailHandler.ts:2599:17
at transporter.send.args (node_modules/nodemailer/lib/mailer/index.js:226:21)
at connection.send (node_modules/nodemailer/lib/smtp-transport/index.js:247:32)
at callback (node_modules/nodemailer/lib/smtp-connection/index.js:435:13)
at stream._createSendStream (node_modules/nodemailer/lib/smtp-connection/index.js:458:24)
at SMTPConnection._actionSMTPStream (node_modules/nodemailer/lib/smtp-connection/index.js:1481:20)
at SMTPConnection._responseActions.push.str (node_modules/nodemailer/lib/smtp-connection/index.js:968:22)
at SMTPConnection._processResponse (node_modules/nodemailer/lib/smtp-connection/index.js:764:20)
at SMTPConnection._onData (node_modules/nodemailer/lib/smtp-connection/index.js:570:14)
Комментарии:
1. Можете ли вы опубликовать код для самого теста? Это поможет диагностировать происходящее. Вот пример асинхронности Jest и пример проблемы с GitHub , чтобы дать вам некоторое представление о вещах, которые могут вызывать ошибки такого типа.
2. @ty2k. Я обновил код, пожалуйста, проверьте. Я уже оформил документы, но не могу выяснить
3. Ознакомьтесь с разделом обратных вызовов в документации Jest по async, в частности с разделом, который передается
done
в качестве аргумента. Также есть этот пост в выпуске Supertest , который имеет ту же проблему, что и у вас. По сути, ваши тесты завершаются до завершения работы вашего сервера.
Ответ №1:
Я использовал тестовый пример react-native по умолчанию (см. Ниже), когда Cannot log after tests are done
произошло.
it('renders correctly', () => {
renderer.create(<App />);
});
По-видимому, проблема заключалась в том, что тест завершился, но ведение журнала все еще было необходимо. Поэтому я попытался выполнить обратный вызов в тестовом примере асинхронно, надеясь, что тест не завершится немедленно:
it('renders correctly', async () => {
renderer.create(<App />);
});
И это сработало. Однако я очень мало представляю, что такое внутренняя работа.
Комментарии:
1. К сожалению, у меня не работает! Примечание: в App.js Я просто отображаю конфигурацию навигационного компонента «NavigationContainer»
Ответ №2:
Если вы используете в своем коде тип async / await, то эта ошибка может возникнуть при вызове async
функции без await
ключевого слова.
В моем случае я определил функцию, подобную приведенной ниже,
async getStatistics(headers) {
....
....
return response;
}
Но я вызвал этот метод как getStatistics(headers)
вместо await getStatistics(headers)
.
Когда я включил await
, это сработало нормально, и проблема была решена.
Ответ №3:
В моем случае при использовании nodejs jest supertest проблема заключалась в том, что когда я import app from "./app"
обращаюсь к своему тестовому файлу, чтобы что-то сделать с помощью supertest ( request(app)
), я фактически импортирую с помощью app.listen()
, потому что при экспорте app
экспорт также учитывается app.listen()
, но нам не нужны app.listen()
тесты, и это выдает ошибку
«Не удается войти в систему после выполнения тестов.Вы забыли дождаться чего-то асинхронного в вашем тесте?»
Здесь все в одном файле (вот в чем проблема!)
const app = express();
app.use(express.json());
// ROUTES
app.get("/api", (req, res) => {
res.json({ message: "Welcome to Blog API!" });
});
app.use("/api/users", usersRoutes);
app.use("/api/blogs", blogsRouter);
// The server will start only if the connection to database is established
mongoose
.connect(process.env.MONGO_URI!)
.then(() => {
console.log("MongoDB est connecté");
const port = process.env.PORT || 4000;
app.listen(port, () => console.log(`The server is running on port: ${port}`));
})
.catch(err => {
console.log(err);
});
export default app;
Чтобы решить эту проблему, я создал 2 отдельные папки:
// 1) app.ts
Куда я помещаю все материалы для своего const app = express()
, маршруты и т.д. И экспортирую приложение
dotenv.config();
const app = express();
app.use(express.json());
// ROUTES
app.get("/api", (req, res) => {
res.json({ message: "Welcome to Blog API!" });
});
app.use("/api/users", usersRoutes);
app.use("/api/blogs", blogsRouter);
export default app;
// 2) index.ts
Куда я помещаю app.listen() and mongoose.connection()
и импортирую app
*import mongoose from "mongoose";
import app from "./app";
// The server will start only if the connection to database is established
mongoose
.connect(process.env.MONGO_URI!)
.then(() => {
console.log("MongoDB est connecté");
const port = process.env.PORT || 4000;
app.listen(port, () => console.log(`The server is running on port: ${port}`));
})
.catch(err => {
console.log(err);
});*
Комментарии:
1. Ссылка . на 32-й минуте он объясняет проблему
Ответ №4:
Это случилось со мной, потому что у меня был бесконечный цикл while (true)
. В моем случае я смог добавить метод для установки значения цикла на основе пользовательского ввода, вместо значения true по умолчанию.
Ответ №5:
Лично мне также нужно было добавить await
перед expect()
вызовом, чтобы остановить эту ошибку (и async
перед test()
функцией обратного вызова).
Также вызвано и исправлено, что Jest не обнаруживал покрытие в строках кода, выдававшего ошибку!
test("expect error to be thrown for incorrect request", async () => {
await expect(
// ^ added this
async () => await getData("i-made-this-up")
).rejects.toThrow(
"[API] Not recognised: i-made-this-up"
);
});
getData()
возвращает вызов Axios, и в этом случае ошибка перехватывается catch
и повторно выдается.
const getData = async (id) => {
return await axios
.get(`https://api.com/some/path?id=${id}`)
.then((response) => response.data)
.catch((error) => {
if (error?.response?.data?.message) {
console.error(error) // Triggered the error
throw new Error("[API] " error.response.data.message);
}
throw error;
});
};
Ответ №6:
Я решил это с помощью переменных env:
if (process.env.NODE_ENV !== 'test') {
db.init().then(() => {
app.listen(PORT, () => {
console.log('API lista por el puerto ', PORT)
})
}).catch((err) => {
console.error(err)
process.exit(1)
})
} else {
module.export = app
}
Ответ №7:
В моем случае ошибка была вызвана тем, что асинхронное соединение Redis все еще подключено к сети. Только что добавил метод afterall для выхода из Redis и смог снова просмотреть журнал.
Работа с Typescript 4.4.2:
test("My Test", done => {
let redisUtil: RedisUtil = new RedisUtil();
let redisClient: Redis = redisUtil.redis_client();
done();
});
afterAll(() => {
redisClient.quit();
});
Ответ №8:
Я столкнулся с теми же предупреждениями. Однако исправление немного странное:
Скрипт модульного тестирования jest импортирует функцию (которая не экспортируется из src /). После того, как я добавил export
в тестируемую функцию. Ошибка исчезает.
Ответ №9:
Также не забудьте продлить время ожидания, если у вас длительный тест с использованием
jest.setTimeout();
В моем случае я просматриваю вызовы API и веду журнал, поэтому он будет расширяться после тайм-аута jest по умолчанию, поэтому я получал ошибку.
Ответ №10:
У меня была похожая проблема:
Cannot log after tests are done. Did you forget to wait for something async in your test?
Attempted to log "Warning: You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. ".
Это произошло из-за отсутствия static
ключевого слова. Этот код вызвал проблему:
class MyComponent extends React.Component<Props, State> {
propTypes = {
onDestroy: PropTypes.func,
}
}
Это должно было быть:
class MyComponent extends React.Component<Props, State> {
static propTypes = {
onDestroy: PropTypes.func,
}
}