简体   繁体   English

在承诺中测试承诺

[英]Testing promises within promises

I used to have the following code: 我以前有以下代码:

function makeCall(userInfo) {
  api.postUser(userInfo).then(response => {
    utils.redirect(response.url);
  })

  // other logic
  return somethingElse;
}

And I was able to write a test that looked like this: 而且我能够编写如下所示的测试:

const successPromise = Promise.resolve({ url: 'successUrl' })

beforeEach(function() {
  sinon.stub(api.postUser).returns(successPromise);
}

afterEach(function() {
  api.postUser.restore();
}

it "calls API properly and redirects" do
  makeCall({});  
  expect(api.postUser).calledWith(userInfo).toBe(true);
  successPromise.then(() => {
    expect(utils.redirect.calledWith('successUrl')).toBe(true);
    done();
  }
emd

And everything was green. 一切都是绿色的。

Now, I had to add another promise to make another external call, before doing the api postUser call, so my code looks like this: 现在,在执行api postUser调用之前,我不得不添加另一个承诺来进行另一个外部调用,因此我的代码如下所示:

function makeCall(names) {
  fetchUserData(names).then(userData => {
    return api.postUser(userData).then(response => {
     utils.redirect(response.url);
    })
  })

  // other logic
  return somethingElse;
 }

where fetchUseData is a chain of many promises, such like: 其中fetchUseData是许多承诺的链,例如:

function fetchNames(names) {
  // some name regions
  return Promise.all(names);
}
function fetchUserData(names) {
  fetchUsersByNames(names).then(users => {
    // For now we just choose first user
    {
      id: users[0].id,
      name: users[0].name,
    }
  });
}

And the tests I had fail. 而且我的测试失败了。 I am trying to understand how to change my tests to make sure that I am still testing that I do the final API call properly and the redirect is also done. 我试图了解如何更改测试,以确保仍在测试是否正确执行了最终的API调用,并且重定向也已完成。 I want to stub what fetchUserData(names) , to prevent doing that HTTP call. 我想存根什么fetchUserData(names) ,以防止进行该HTTP调用。

You should add a return statement, otherwise you are not returning promises nowhere: 您应该添加一个return语句,否则您将无处返回诺言:

function fetchNames(names) {
  // some name regions
  return Promise.all(names);
}
function fetchUserData(names) {
  return fetchUsersByNames(names).then(users => {
    // For now we just choose first user
    {
      id: users[0].id,
      name: users[0].name,
    }
  });
}

So when you are using Promise.all(), then you will have as result of the promise an array with all the value returned by all the promises. 因此,当您使用Promise.all()时,作为promise的结果,您将获得一个数组,其中包含所有promise返回的所有值。 So then this method should look like this when called: 因此,此方法在调用时应如下所示:

fetchNames(names).then((arrayOfResolvedPromises) => {
 // here you will have all your promised resolved and the array holds all the results
});

So inside your test you can move your done inside the block where all the promises will be resolved. 因此,在测试内部,您可以将完成的工作移到所有承诺都将得到解决的模块中。

In addition, I strongly suggest you to use a library as chai-as-promised for testing promises. 另外,我强烈建议您使用约定的库来测试Promise。 It has a lot of nice methods for testing your promises. 它有很多不错的方法来测试您的承诺。

https://github.com/domenic/chai-as-promised https://github.com/domenic/chai-as-promised

You're not using promises correctly. 您没有正确使用Promise。 Your code doesn't have a single return statement, when it should have several (or it should be using arrow functions in such a way that you don't need them, which you're not doing). 您的代码没有一个return语句,而应该包含多个return语句(或者应该以不需要它们的方式使用箭头函数,而您并没有这样做)。

Fix your code: 修正您的代码:

function makeCall(names) {
  // v---- return
  return fetchUserData(names).then(userData => {
    // v---- return
    return api.postUser(userData).then(response => {
      utils.redirect(response.url);
    })
  })
 }


function fetchUserData(names) {
  // v---- return
  return fetchUsersByNames(names).then(users => {
    // For now we just choose first user
    // v---- return
    return {
      id: users[0].id,
      name: users[0].name,
    }
  });
}

Once you've done that, you can have your test wait for all of the operations to finish. 完成此操作后,您可以让测试等待所有操作完成。

Test code: 测试代码:

makeCall(['name']).then(() =>
  expect(api.postUser).calledWith(userInfo).toBe(true);
  expect(utils.redirect.calledWith('successUrl')).toBe(true);
  done();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM