在 JavaScript 的 Promise 中,如何从 sinon.spy 中获取回调参数?

3

我正在使用mocha和sinon进行测试,以从HTTP请求的promise范围内获取回调值,但由于promise的异步性质,它不起作用。这是因为当sinon.spy检查回调时,它已经消失了并变为空或未定义。以下是测试代码:

 it('should issue GET /messages ', function() {
  server.respondWith('GET', `${apiUrl}/messages?counter=0`, JSON.stringify([]));
  let callback = sinon.spy();
  Babble.getMessages(0, callback);
  server.respond();
  sinon.assert.calledWith(callback, []);
});

并承诺:
function requestPoll(props) {
    return new Promise(function(resolve, reject) {
            var xhr = new XMLHttpRequest();
            xhr.open(props.method, props.action);
            xhr.timeout = 500; // time in milliseconds
            if (props.method === 'post' ) {
                    xhr.setRequestHeader('Content-Type', 'application/json');
            }
            xhr.addEventListener('load', function(e) {
                    resolve(e.target.responseText);
            });

            xhr.send(JSON.stringify(props.data));


    });
}

我正在尝试从sinon.spy回调中获取的调用

getMessages: function(counter, callback){

            requestPoll({

                            method: "GET",
                            action: "http://localhost:9090/messages?counter="+counter

            }).then(function(result){

                    callback(result);
            });


        }

sinon.spy 表示它没有任何参数(由于异步功能)。我试图寻找一种方法来获取作用域外的结果并将其放在回调中,但我发现这是不可能的。我也尝试了解决和承诺返回,但没有成功。

如何让这个单元测试通过?

编辑:
这是我的尝试:

getMessages: function(counter, callback){

            var res;
            res = httpRequestAsync("GET",'',"http://localhost:9097/messages?counter=",counter);

            console.log(res);
            if(res!="")
                    callback( JSON.parse(res) );                      
        }

我将请求放在一个单独的函数中:

我将请求放在一个单独的函数中:

function httpRequestAsync(method,data,theUrl,counter)
    {

            return requestPoll({

                    method: method,
                    action: theUrl+counter,
                    data: data

            }).then(JSON.parse);

    }

它返回的是res作为承诺,而在其原型中有我需要的承诺值。 enter image description here

我该如何访问那个承诺的值?


你能给我展示一下吗?我尝试了几次返回promise。@Bergi,在“then”下面我需要写什么才能返回一个正确的promise? - Shaked
你只需要省略掉 then,并在表达式前面加上 return。请展示一下你的尝试。 - Bergi
删除除了 return requestPoll({…}); 以外的所有行,并删除 callback 参数。如果需要解析结果,请在其后添加 .then(JSON.parse)。然后更改所有调用,使用 promise 替代传递回调函数。 - Bergi
我确实需要传递一个回调函数。是否有使用回调参数使测试通过的选项? - Shaked
@Bergi 嗯,我基本上按照你说的做了,并将其放在一个单独的请求函数中。在发布这个问题之前,我已经尝试过这个方法。现在我遇到了与之前相同的问题。我该如何访问原型承诺值?我知道这是不可能的。 - Shaked
显示剩余4条评论
1个回答

2
我建议您不要混合使用Promises和回调函数。如果您已经有基于Promise的函数,请坚持使用它。
首先,将getMessages修改为不中断Promise链,并使其返回一个Promise。
getMessages: function(counter) {
  return requestPoll({
    method: "GET",
    action: "http://localhost:9090/messages?counter=" + counter
  }).then(JSON.parse)
}

然后在你的测试中使用这个Promise。
it('should issue GET /messages ', function() {
  server.respondWith('GET', `${apiUrl}/messages?counter=0`, JSON.stringify([{testdata}]));
  const gettingMessages = Babble.getMessages(0);
  server.respond();

  // return a promise so testing framework knows the test is async
  return gettingMessages.then(function(messages) {
      // make assertion messages is actually testdata
  })
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接