Я создал экспресс-приложение с использованием Typescript, которое подключается к MongoDB с помощью созданного мною синглтона. при обычном запуске приложения с использованием узла server.js все работает как положено. Однако, когда я пытаюсь использовать jest для тестирования, соединение возвращается как нулевое, и из журналов, которые я поставил, кажется, что он не выполняет метод подключения Монго внутри конструктор MongoDBClient.
Я пытался использовать также ts-jest, но безуспешно, он просто не может получить соединение mongoDB, как при использовании узла server.js. Я также добавляю файл .env, используя env-cmd jest.
server.ts
import dotenv from "dotenv";
import path from "path";
// config path for dotenvfile
dotenv.config({path: path.join(__dirname, "..", ".env")});
import {app} from "./app";
import {WatsonHandlerLogger} from "./logger/watsonHandlerLogger";
import {MongoDBClient} from "./db/mongoDBClient";
// instantiate logger
const logger = WatsonHandlerLogger.getInstance();
// only start the server if managed to establish connection to mongoDB
MongoDBClient.getInstance().then((client) => {
if(!client)
{
throw new Error("client was not defined. connection to mongo db might be established but wan't passed correctly");
}
else
{
const server =
app.listen(process.env.PORT || 3100, (): void => {
logger.logger.info('Server is up and running!');
console.log(`app is running on port ${process.env.PORT}`);
});
//creates shutdown manager for the server
shutdownManager = new GracefulShutdownManager(server);
}
}).catch((err) => {
logger.logger.error(err);
});
app.ts
import express from "express";
import path from "path";
import bodyParser from "body-parser";
import util from "util"
import {WatsonHandlerLogger} from "./logger/watsonHandlerLogger";
import {MongoDBClient} from "./db/mongoDBClient";
export const app = express();
app.use(bodyParser.json()); // for parsing application/json
// instantiate logger
const logger = WatsonHandlerLogger.getInstance();
app.get("/", (req: any, res: any) => {
return res.status(200).send("hello");
});
/**
* Recives a message from Conversation.
*/
app.get("/api/messages", async (req, res) => {
const mongoClient = await MongoDBClient.getInstance();
if(mongoClient === null)
{
logger.logger.error('mongo client connection is not defined!');
logger.logger.info(util.inspect(mongoClient,{depth:6}));
return res.status(500).json({Error: "Error occured while trying to use mongoDB connection"});
}
try
{
logger.logger.info(mongoClient.client);
await mongoClient.client.db(process.env.MONGO_DB_NAME)
.collection(process.env.MONGO_COLLECTION)
.find({}).forEach((document) => {
console.log(document);
});
return res.status(200).json({message: "seems ok so far"});
}
catch(err)
{
logger.logger.error(err);
return res.status(500).json({Error: "Error occured while trying to use mongoDB connection"});
}
});
MongoDBClient.ts
import path from "path";
import mongo from "mongodb";
import { loggers } from "winston";
const mongoClient = mongo.MongoClient;
import {WatsonHandlerLogger} from "../logger/watsonHandlerLogger";
const logger = WatsonHandlerLogger.getInstance();
export class MongoDBClient {
private static instance: MongoDBClient;
private static url = `mongodb+srv://${process.env.MONGO_USERNAME}:${process.env.MONGO_PASSWORD}@${process.env.MONGO_HOST}?retryWtites=true`;
private static mongoPoolSize = process.env.MONGO_POOL_SIZE ? parseInt(process.env.MONGO_POOL_SIZE) : 10;
private _client: mongo.MongoClient | null;
// private constructor
private constructor(mongoUrl : string, poolSize: number)
{
this._client = null;
logger.logger.info('made it to constructor');
mongoClient.connect(mongoUrl, {
useNewUrlParser: true,
poolSize:poolSize
}).then(client => {
this._client = client;
logger.logger.info('even made it to then..');
}).catch(err => {
logger.logger.error("failed to connect to mongoDB.." + err);
throw new Error("failed to connect to mongoDB..");
});
}
get client() : mongo.MongoClient | null
{
return this._client;
}
/**
* @remarks
* Singelton of MongoDBClient which will be used across watson handler app
*/
static async getInstance() :Promise<MongoDBClient>
{
logger.logger.info('made it to getInstance');
if(!this.instance)
{
// instantiate logger object
try
{
this.instance = new MongoDBClient(this.url, this.mongoPoolSize);
}
catch(err)
{
logger.logger.info('very weird ' + err);
throw new Error(err);
}
}
// return initialized logger
return this.instance;
}
}
main.test.js
const request = require('supertest');
const {app} = require('../src/app');
const {MongoDBClient} = require("../src/db/mongoDBClient");
const {WatsonHandlerLogger} = require('../src/logger/watsonHandlerLogger');
beforeAll (async (done) => {
const logger = WatsonHandlerLogger.getInstance();
try
{
logger.logger.info('inside testing');
await MongoDBClient.getInstance();
done();
}
catch(err)
{
console.log('failed to connect ' + err)
done();
}
}, 20000);
test('should check server is up and running', async() => {
const response = await request(app).get('/');
expect(response.statusCode).toBe(200);
});
test('should check mongoDB connection', async() => {
const response = await request(app).get('/api/messages');
expect(response.statusCode).toBe(200);
});
afterAll (async (done) => {
try
{
const mongoClient = await request(MongoDBClient.getInstance());
await mongoClient.client.close();
done();
}
catch(err)
{
console.log('failed to connect ' + err)
done();
}
}, 20000);
Я ожидаю, что тестирование будет вести себя как команда 'node src / server.js', которая прекрасно работает. фактический результат, который я получаю, заключается в том, что из / api / messages я получаю сообщение об ошибке, которое говорит, что не может использовать свойство'db 'со значением NULL, а также ту же ошибку, когда я использую await mongoClient.client.close () только с функцией' close ' вместо 'db' (что означает, что клиент возвращает значение null и даже не вызывает метод монго соединения).
Спасибо!