I am running a test case which should add a document
in areas
collection
in Questions
database in mongo
using mongoose
.
I am facing two problems though. Why?
test
database instead of Questions
.This function does most of the heavy lifting
async function addQuestion (description,hints,topic) {
var q = null;
console.log(`adding question:`);
console.log(`description: ${description}`);
console.log(`hints: ${hints}`);
console.log(`topic: ${topic}`);
var db = mongoUtils.dbclass.getDb();
console.log(`addQuestion: db is ${util.inspect(db)}`);
console.log(`looking for collection for topic: ${topic}`);
const topicSpecificCollection = await db.collection(topic);
console.log(`got collection ${util.inspect(topicSpecificCollection)}`);
/*in the mongoose.model call below, the first argument is the singular name of the collection the model is for.
Mongoose automatically looks for the plural, lowercased version of your model name.
The model `area` is for the `areas` collection in the database. */
const Question = mongoose.model(topic, questionSchema); //I ASSUME THAT IF TOPIC IS `area` THEN MONGOOSE WILL ADD THE DOCUMENT IN `areas` COLLECTION
q = Question({
description: description,
hints: hints,
topic: topic
});
await q.save()
.then ((result) => {
console.log(`added question ${result}`);
return result;
})
.catch ( (err)=>{
console.log(`error in adding question: ${err}`);
return null;
});
}
The schema
is
const mongoose = require("mongoose");
const questionSchema = new mongoose.Schema({
description: String,
hints: [String],
topic: String
});
module.exports = questionSchema;
result
above, the calling function gets undefined
. See traces below.The test is
it("should add a question about calculating area in Area collection", async ()=>{
const topic = "area"; //THIS SHOULD BE ADDED IN `areas` COLLECTION?
const description = "description of question on area";
const hints = ["area hint 1", "area hint 2"];
req = {
"description": description,
"hints" : hints,
"topic" :topic
}
res = {
}
const Question = mongoose.model(topic, questionSchema);
q = Question({
description: description,
hints: hints,
topic: topic
});
const expectedResponse = {'questionAdded': req}
await questionControllerModule.addQuestionHandler(req,res)
.then((result) => {
console.log(`added question ${result}`); //TRACES SHOW THAT result IS undefined
expect(result).toBe(q);
})
});
The output is
console.log
adding question:
at log (controllers/question.js:11:11)
console.log
description: description of question on area
at log (controllers/question.js:12:11)
console.log
hints: area hint 1,area hint 2
at log (controllers/question.js:13:11)
console.log
topic: area
at log (controllers/question.js:14:11)
console.log
addQuestion: db is Db {
s: {
options: {
enableUtf8Validation: true,
forceServerObjectId: false,
pkFactory: [Object],
raw: false,
readPreference: [ReadPreference],
retryWrites: true
},
readPreference: ReadPreference {
mode: 'primary',
tags: undefined,
hedge: undefined,
maxStalenessSeconds: undefined,
minWireVersion: undefined
},
bsonOptions: {
raw: false,
useBigInt64: false,
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
ignoreUndefined: false,
bsonRegExp: false,
serializeFunctions: false,
fieldsAsRaw: {},
enableUtf8Validation: true
},
pkFactory: { createPk: [Function: createPk] },
readConcern: undefined,
writeConcern: undefined,
**namespace: MongoDBNamespace { db: 'Questions', collection: undefined }** //DON'T KNOW WHY collection IS undefined.
},
client: <ref *1> MongoClient {
_events: [Object: null prototype] {
serverDescriptionChanged: [Function (anonymous)]
},
_eventsCount: 1,
_maxListeners: 0,
mongoLogger: MongoLogger {
error: [Function: bound log],
warn: [Function: bound log],
info: [Function: bound log],
debug: [Function: bound log],
trace: [Function: bound log],
componentSeverities: [Object],
maxDocumentLength: 1000,
logDestination: [Object]
},
s: {
url: 'mongodb://0.0.0.0:27017/',
bsonOptions: [Object],
namespace: [MongoDBNamespace],
hasBeenClosed: false,
sessionPool: [ServerSessionPool],
activeSessions: [Set],
options: [Getter],
readConcern: [Getter],
writeConcern: [Getter],
readPreference: [Getter],
isMongoClient: [Getter]
},
topology: Topology {
_events: [Object: null prototype],
_eventsCount: 26,
_maxListeners: undefined,
client: [Circular *1],
selectServerAsync: [Function (anonymous)],
s: [Object],
[Symbol(kCapture)]: false,
[Symbol(waitQueue)]: [List]
},
connectionLock: undefined,
[Symbol(kCapture)]: false,
[Symbol(options)]: [Object: null prototype] {
hosts: [Array],
compressors: [Array],
connectTimeoutMS: 30000,
directConnection: false,
driverInfo: [Object],
enableUtf8Validation: true,
forceServerObjectId: false,
heartbeatFrequencyMS: 10000,
keepAlive: true,
keepAliveInitialDelay: 120000,
loadBalanced: false,
localThresholdMS: 15,
maxConnecting: 2,
maxIdleTimeMS: 0,
maxPoolSize: 100,
minPoolSize: 0,
minHeartbeatFrequencyMS: 500,
monitorCommands: false,
noDelay: true,
pkFactory: [Object],
raw: false,
readPreference: [ReadPreference],
retryReads: true,
retryWrites: true,
serverSelectionTimeoutMS: 30000,
socketTimeoutMS: 0,
srvMaxHosts: 0,
srvServiceName: 'mongodb',
waitQueueTimeoutMS: 0,
zlibCompressionLevel: 0,
dbName: 'test',
userSpecifiedAuthSource: false,
userSpecifiedReplicaSet: false,
mongoLoggerOptions: [Object],
metadata: [Object],
[Symbol(@@mdb.enableMongoLogger)]: false
}
}
}
at log (controllers/question.js:17:11)
console.log
looking for collection for topic: area
at log (controllers/question.js:18:11)
console.log
got collection Collection {
s: {
db: Db { s: [Object], client: [MongoClient] },
options: {
raw: false,
useBigInt64: false,
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
ignoreUndefined: false,
bsonRegExp: false,
serializeFunctions: false,
fieldsAsRaw: {},
enableUtf8Validation: true,
readPreference: [ReadPreference]
},
**namespace: MongoDBCollectionNamespace { db: 'Questions', collection: 'area' },** //HERE I SEE THE COLLECTION area THOUGH
pkFactory: { createPk: [Function: createPk] },
readPreference: ReadPreference {
mode: 'primary',
tags: undefined,
hedge: undefined,
maxStalenessSeconds: undefined,
minWireVersion: undefined
},
bsonOptions: {
raw: false,
useBigInt64: false,
promoteLongs: true,
promoteValues: true,
promoteBuffers: false,
ignoreUndefined: false,
bsonRegExp: false,
serializeFunctions: false,
fieldsAsRaw: {},
enableUtf8Validation: true
},
readConcern: undefined,
writeConcern: undefined
},
client: <ref *1> MongoClient {
_events: [Object: null prototype] {
serverDescriptionChanged: [Function (anonymous)]
},
_eventsCount: 1,
_maxListeners: 0,
mongoLogger: MongoLogger {
error: [Function: bound log],
warn: [Function: bound log],
info: [Function: bound log],
debug: [Function: bound log],
trace: [Function: bound log],
componentSeverities: [Object],
maxDocumentLength: 1000,
logDestination: [Object]
},
s: {
url: 'mongodb://0.0.0.0:27017/',
bsonOptions: [Object],
namespace: [MongoDBNamespace],
hasBeenClosed: false,
sessionPool: [ServerSessionPool],
activeSessions: [Set],
options: [Getter],
readConcern: [Getter],
writeConcern: [Getter],
readPreference: [Getter],
isMongoClient: [Getter]
},
topology: Topology {
_events: [Object: null prototype],
_eventsCount: 26,
_maxListeners: undefined,
client: [Circular *1],
selectServerAsync: [Function (anonymous)],
s: [Object],
[Symbol(kCapture)]: false,
[Symbol(waitQueue)]: [List]
},
connectionLock: undefined,
[Symbol(kCapture)]: false,
[Symbol(options)]: [Object: null prototype] {
hosts: [Array],
compressors: [Array],
connectTimeoutMS: 30000,
directConnection: false,
driverInfo: [Object],
enableUtf8Validation: true,
forceServerObjectId: false,
heartbeatFrequencyMS: 10000,
keepAlive: true,
keepAliveInitialDelay: 120000,
loadBalanced: false,
localThresholdMS: 15,
maxConnecting: 2,
maxIdleTimeMS: 0,
maxPoolSize: 100,
minPoolSize: 0,
minHeartbeatFrequencyMS: 500,
monitorCommands: false,
noDelay: true,
pkFactory: [Object],
raw: false,
readPreference: [ReadPreference],
retryReads: true,
retryWrites: true,
serverSelectionTimeoutMS: 30000,
socketTimeoutMS: 0,
srvMaxHosts: 0,
srvServiceName: 'mongodb',
waitQueueTimeoutMS: 0,
zlibCompressionLevel: 0,
dbName: 'test',
userSpecifiedAuthSource: false,
userSpecifiedReplicaSet: false,
mongoLoggerOptions: [Object],
metadata: [Object],
[Symbol(@@mdb.enableMongoLogger)]: false
}
}
}
at log (controllers/question.js:20:11)
console.log //THIS PROBABLY IS BECAUSE THE QUESTION GOT ADDED IN TEST DATABASE
added question {
description: 'description of question on area',
hints: [ 'area hint 1', 'area hint 2' ],
topic: 'area',
_id: new ObjectId("64f380a9df8906232c783779"),
__v: 0
}
at log (controllers/question.js:33:13)
console.log
**added question undefined** //BUT THE CALLIG FUNCTION GETS UNDEFINED RETURN VALUE
at log (controllers/question.js:71:13)
console.log
added question undefined
at log (test/question.test.js:49:17)
console.log
closing database connection
at Object.log (test/question.test.js:15:11)
FAIL test/question.test.js
Operations to manage questions should work
× should add a question about calculating area in Area collection (152 ms)
● Operations to manage questions should work › should add a question about calculating area in Area collection
expect(received).toBe(expected) // Object.is equality
Expected: {"_id": "64f380a9df8906232c783778", "description": "description of question on area", "hints": ["area hint 1", "area hint 2"], "topic": "area"}
Received: undefined
48 | .then((result) => {
49 | console.log(`added question ${result}`);
> 50 | expect(result).toBe(q);
| ^
51 | })
52 | });
53 | });
at toBe (test/question.test.js:50:24)
at Object.<anonymous> (test/question.test.js:47:5)
The result in MongoCompass
Code to connect to database
dbConnectMongoose: async function (){
console.log(`trying to connect to uri ${process.env.DATABASE_URL}`);
const connection = await mongoose.connect(process.env.DATABASE_URL); //DATABASE_URL=mongodb://0.0.0.0:27017
console.log(`connected to Mongo.`);
var localdbClient = connection.connections[0].client;
var localdb;
console.log(`got MongoClient: `); //for circular objects, JSON.stringify doesn't work
try {
localdb = localdbClient.db(process.env.DATABASE);
console.log(`connected to database ${localdb.databaseName}`);
const collections = await localdb.collections();
collections.forEach(c => {console.log(`got collection ${c.collectionName}`)})
} catch(exception) {
console.log(`something bad happened in dbconnect: ${exception}`);
} finally {
this.db = localdb;
this.dbClient = localdbClient;
this.dbConnection = connection;
console.log(`db Class db is ${this.db}`);
console.log(`db Class dbClient is ${this.dbClient}`);
console.log(`db Class dbConnection is ${this.dbConnection}`);
}
}
You need to specify the database name in the connection url, like this:
DATABASE_URL=mongodb://0.0.0.0:27017/questions
By default, if omitted it connects to the test
database.
For your second problem, you are mixing async-await
, with Promise
methods. You should do either this:
return q.save()
.then ((result) => {
console.log(`added question ${result}`);
return result;
})
.catch ( (err)=>{
console.log(`error in adding question: ${err}`);
return null;
});
Or try this:
try {
const result = await q.save();
console.log(`added question ${result}`);
return result;
} catch(err){
console.log(`error in adding question: ${err}`);
return null;
};
Update this behavior in all of your functions.