gpt4 book ai didi

node.js - 在 Mocha 测试中的 for 循环中进行顺序 Mongoose 查询

转载 作者:太空宇宙 更新时间:2023-11-04 00:37:53 25 4
gpt4 key购买 nike

我正在尝试使用 mocha 作为我的 API 应用程序的测试驱动程序。

我有一个包含用户名和歌曲名称的 json,我正在尝试将其提供给 API 端点。

json:

{
"description": "hold the lists that each user heard before",
"userIds":{
"a": ["m2","m6"],
"b": ["m4","m9"],
"c": ["m8","m7"],
"d": ["m2","m6","m7"],
"e": ["m11"]
}
}

假设用户和歌曲架构只是 _id 和名称。我想要做的是解析 json 文件后,通过按名称对“a”进行 Mongoose 查找,将“a”转换为 user_id,假设 id=0。将每个“m2”按名称转换为song_id(假设id=1),然后调用请求,http://localhost:3001/listen/0/1

这是迄今为止我的 Mocha 测试:

测试.js:

it('adds the songs the users listen to', function(done){
var parsedListenJSON = require('../listen.json')["userIds"];
//console.log(parsedListenJSON);
for (var userName in parsedListenJSON) {
if (parsedListenJSON.hasOwnProperty(userName)) {
var songs = parsedListenJSON[userName];
var currentUser;
//console.log(userName + " -> " + songs);
var userQuery = User.findOne({'name': userName})
userQuery.then(function(user){
//console.log("user_id: " + user["_id"]);
currentUser = user;
});

for (var i=0; i<songs.length; i++)
{
//console.log(songs[i]);
var songQuery = Song.findOne({'name': songs[i]})
songQuery.then(function(song){
console.log("user_id: " + currentUser["_id"]);
console.log("song_id: " + song["_id"]);
// need to ensure we have both the user_id and song_id

api_request = "http://localhost:3001/listen/" + currentUser["_id"] + "/" + song["_id"];
console.log(api_request);
// listen/user_id/song_id
//.post('http://localhost:3001/listen/0/1')
request
.post(api_request)
.end(function(err, res){
expect(res.status).to.equal(200);
});

});
}
}
}
done();
})

问题:

1) 在进行 API 校准之前,我需要确保拥有 user_id 和 Song_id。现在,每个 User.findOne 和 Song.findOne 查询都有自己的 then 子句。我通过 currentUser 变量将 user_id 传递到歌曲查询的 then block 中。但由于查询是异步的,我认为这是不正确的。如何构造此代码,以便在执行了 then block 后继续执行 API 调用。

2)当我按原样运行代码时,只有第一个用户被执行,而不是其余的,IE。打印输出是:用户 ID:0歌曲 ID:1 http://localhost:3001/listen/0/1用户 ID:0歌曲 ID:5 http://localhost:3001/listen/0/5

3) API 端点与 postman 一起使用,并在下面的更简单的 Mocha 测试中进行。但它在我原来的代码中似乎不起作用。

var request = require('superagent');
var expect = require('expect.js');
var User = require('../models/user');
var Song = require('../models/song');
var mongoose = require('mongoose');
mongoose.connect('localhost/TestSongRecommender');
...
it('adds the songs', function(){
request
.post('http://localhost:3001/listen/0/2')
.end(function(res){
expect(res.status).to.equal(200);
});
});

更新:

async.forEach 方法有效。这是我的最终片段:

更新了 test.js

var request = require('superagent');
var expect = require('expect.js');
var async = require('async');
var User = require('../models/user');
var Song = require('../models/song');
var mongoose = require('mongoose');
mongoose.connect('localhost/Test');

describe('song recommendations', function(){
it('adds the songs the users listen to', function(done){
var parsedListenJSON = require('../listen.json')["userIds"];
//console.log(parsedListenJSON);
async.forEach(Object.keys(parsedListenJSON), function forAllUsers(userName, callback) {
var songs = parsedListenJSON[userName];
//var currentUser;
//console.log(userName + " -> " + songs);
var userQuery = User.findOne({'name': userName})
userQuery.then(function(user){
//console.log("user_id: " + user["_id"]);
//console.log(songs);
//currentUser = user;
async.forEach(songs, function runSongQuery(songName, smallback) {
//console.log(songName);
var songQuery = Song.findOne({'name': songName})
songQuery.then(function(song){
//console.log("user_id: " + user["_id"]);
//console.log("song_id: " + song["_id"]);
// need to ensure we have both the user_id and song_id
api_request = "http://localhost:3001/listen/" + user["_id"] + "/" + song["_id"];
console.log(api_request);
// listen/user_id/song_id
//.post('http://localhost:3001/listen/0/1')
request
.post(api_request)
.end(function(err, res){
expect(res.status).to.equal(200);
smallback()
});

});
}, function allSongs(err) {
callback();
})
});
}, function allUserNames(err) {
done()
})
})
});

最佳答案

1&2) 您将需要使用 NPM 中的异步包。您可以在主文件夹中使用命令 npm install async --save 并在代码中使用 var async = require('async') 来获取它。

您必须将每个 for 循环替换为 async.forEach。 async.forEach 接受一个数组和两个函数作为参数。它对数组中的每个项目调用第一个函数,并在所有回调返回后调用第二个函数。

你目前使用 for 循环的方式是行不通的。当异步事物返回时,您的循环已迭代它们(记住非阻塞 IO),并且您的变量不再正确设置。

您还需要设置一些内容,以便仅在所有代码运行后调用“done”。

如果编写正确的话,它最终会看起来像这样:

it('adds the songs the users listen to', function(done){
var parsedListenJSON = require('../listen.json')["userIds"];
//console.log(parsedListenJSON);
async.forEach(parsedListenJSON, function forAllUsers(userName, callback) {
var songs = parsedListenJSON[userName];
//console.log(userName + " -> " + songs);
var userQuery = User.findOne({'name': userName})
userQuery.then(function(user){
//console.log("user_id: " + user["_id"]);
var currentUser = user;
async.forEach(songs, function runSongQuery(songName, smallback) {
var songQuery = Song.findOne({'name': songName})
songQuery.then(function(song){
console.log("user_id: " + currentUser["_id"]);
console.log("song_id: " + song["_id"]);
// need to ensure we have both the user_id and song_id

api_request = "http://localhost:3001/listen/" + currentUser["_id"] + "/" + song["_id"];
console.log(api_request);
// listen/user_id/song_id
//.post('http://localhost:3001/listen/0/1')
request
.post(api_request)
.end(function(res){
expect(res.status).to.equal(200);
smallback()
});

});
}, function allRan(err) {
callback();
})
});
}, function allUserNames(err) {
done()
})
})

3) 您将需要使用测试框架来测试您的 API。我推荐supertest 。进行 super 测试后,需要您的应用程序和 super 测试:

var request = require('supertest');
var app = require('./testApp.js');

在以下测试中使用它:

request(app)
.post(api_request)
.end(function(res){
expect(res.status).to.equal(200);
smallback()
});

关于node.js - 在 Mocha 测试中的 for 循环中进行顺序 Mongoose 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38188367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com