【问题标题】:unit testing ava + sinon for api call, one of the stub is not workingapi调用的单元测试ava + sinon,其中一个存根不起作用
【发布时间】:2021-06-08 19:04:03
【问题描述】:

我有一个测试用例需要测试一个具有 2 个上层承诺函数的函数。 我存根所有这 3 个函数,前 2 个工作正常,但最后一个似乎没有工作..

classD:

const obj1 = require('./classA');
const obj2 = require('./classB');
const obj3 = require('./classC');

const getTeam = () =>{
    return new Promise((resolve, reject) => {
        obj1.promiseFunc1().then(res1 => {
            if(res1.error){
              reject(res1); 
            }else{
              resolve({Teamid: 1, TeamName: 'goodName'});
            }
    })
}

const getMember = () => {
    return new Promise((resolve, reject) => {
      obj2.promiseFunc2().then(res2 => {
        if(res2.id.length === 0){
          obj3.promiseFunc3().then(res3 => {
            if(res3.error){
              reject(res3); 
            }else{
              getTeam().then(res => {
                 if(res.error){
                    reject(res);
                  }else{
                   resolve(res);
                  }
              });
            }
        })
      }
   })    
 })
}

下面是测试用例:

Test.js

const obj1 = require('./classA');
const obj2 = require('./classB');
const obj3 = require('./classC');
const obj4 = require('./classD');
const sandbox = require('sinon').createSandbox();

test.serial('test getMember', async (t) => {
  sandbox.restore();
  sandbox.stub(obj2, 'promiseFunc2').resolves({id: [], error: false});
  sandbox.stub(obj3, 'promiseFunc3').resolves({status: 200, error: false});

  sandbox.stub(obj4, 'getTeam').resolves({data: [], error: false});

  const result = await obj4.getMember();
  console.log('result :' + JSON.stringify(result));
})

所以我需要为函数 obj4.getMember() 运行测试用例,该函数将调用 obj2.promiseFunc2、obj3.promiseFunc3 和 obj4.getTeam(),它们都返回 Promise。我存根 promiseFunc2 和 promiseFunc3 没有问题。但由于某种原因, obj4.getTeam() 似乎无法正常工作。我返回了 {Teamid: 1, TeamName: 'goodName'} 这是 getTeam() 同一文件中最后一个测试用例的响应...

我希望返回 {data: [], error: false} 这是我存根的结果..

有人知道为什么存根不工作吗?如何让它发挥作用?

非常感谢!

【问题讨论】:

  • 嗨,我不知道发生了什么,但我担心你会把自己画到角落里。如果您测试一个如此耦合的代码库,并且存根深深植根于其内部,您将使您的测试变得脆弱,阻止重构并逐渐放松对代码的控制,而这正是测试应该防止的......您的测试也是难以解析,因为您的代码难以测试。如果我有一个建议:不要测试这段代码,重构它,让它易于测试。并学习如何链接 Promises 以及如何使用 Promise.reject。如果你有时间......
  • 感谢您的回复!不幸的是,代码已经运行了很长时间...我认为我的经理不会允许我更改代码...:(

标签: javascript node.js unit-testing sinon ava


【解决方案1】:

obj4.getMember 调用getTeam 作为函数可能会绕过Simon 的存根。

尝试以下方法:

const obj1 = require('./classA');
const obj2 = require('./classB');
const obj3 = require('./classC');

const obj4 = {};

obj4.getTeam = () =>{
    return new Promise((resolve, reject) => {
        obj1.promiseFunc1().then(res1 => {
            if(res1.error){
              reject(res1); 
            }else{
              resolve({Teamid: 1, TeamName: 'goodName'});
            }
        })
    })
}

obj4.getMember = () => {
    return new Promise((resolve, reject) => {
      obj2.promiseFunc2().then(res2 => {
        if(res2.id.length === 0){
          obj3.promiseFunc3().then(res3 => {
            if(res3.error){
              reject(res3); 
            }else{
              obj4.getTeam().then(res => {
                 if(res.error){
                    reject(res);
                  }else{
                   resolve(res);
                  }
              });
            }
        })
      }
   })    
 })
}
        
module.exports = obj4;

我认为您不应该将模块称为“类”,因为它设置了错误的期望。


对于 Promise 链接,不幸的是您的 API 不会拒绝错误,这会迫使您添加大量错误处理逻辑,但助手可以将这些承诺转换为被拒绝的承诺

const rejectOn = predicate => f => (...xs) =>
    f(...xs).then(x => predicate(x) ? Promise.reject(x) : x);

const error = x => x.error;

有了这个,下面的代码会更容易阅读并且功能相同(假设objN.promiseFuncN 不是带有上下文的方法)。请注意,没有必要在新的 Promise 中包装返回 Promise 的函数,并且返回 Promise 会替换周围的 Promise,从而从代码中删除大量样板。


obj4.getTeam = () => 
    rejectOn(error)(obj1.promiseFunc1)()
    .then(() => ({ Teamid: 1, TeamName: 'goodName' }));


obj4.getMember = () =>
    rejectOn(x => x.id.length)(obj2.promiseFunc2)()
    .then(rejectOn(error)(obj3.promiseFunc3))
    .then(rejectOn(error)(obj4.getTeam));

也许你应该和你的经理谈谈。干净的代码不会减慢您的速度。腐烂的代码会让你慢下来。

【讨论】:

  • 感谢您的回答!你能展示一下测试用例代码应该是怎样的吗?我试图在 js 文件中添加一个 obj4 = {}。 ava 说:cannot stub non-existent property of obj4.getTeam ..
  • 这很奇怪。您尝试在哪个文件中添加obj4 = {}?您是否还添加了 obj4.getTeamobj4.getMember ?另请注意,在我的原始答案中,我忘记在第一个代码块中的obj4.getMember 中将getTeam 替换为obj4.getTeam。我编辑了我的答案。请注意,您的测试代码不必更改(除了添加一个实际的断言,因为它目前没有测试任何东西)
猜你喜欢
  • 2016-10-20
  • 2021-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-10
  • 2020-06-22
  • 1970-01-01
相关资源
最近更新 更多