使用Sinon框架对yield*函数调用进行桩测试

3
我对function*/yield/yield*以及单元测试都很陌生,所以我不确定为什么我的单元测试代码不工作。它使用sinon stubbing和mocha testing framework。我已经阅读了关于function*/yield/yield*的资料,但对我来说仍然很困惑。
使用Co库,我有一个带有yield*function*,它调用另一个function*。我试图用sinon stub来模拟yield*调用的function*,但是stub返回undefined。如果只是yield而不是yield*,则stub会返回正确的响应。
导入:
import * as name from './file';

调用原始生成器函数:

export const func = (a, b, c) => co(secondFunc.bind(this, a, b, c));

函数 secondFunc:

function* secondFunc(a, b, c) {
  try {
    const x = yield* name.get(a); // this is where x is undefined
    // logic
    return value;
  } catch (err) {
    // logic
  }
}

单元测试:

const callback = sinon.stub(name, 'get');
callback.returns(new Promise((resolved, reject) => resolved(response)));

co(func("a", "b", "c")).then((value) => {
    console.log(value);
    done();
}).catch(done);     

(值得注意的是,原始代码并不是我编写的。我只是添加了单元测试。)
2个回答

3
可以通过使用SinonStub#callsFake进行存根化,使其稍微简单一些。
const nameGetStub = sinon.stub(name, "get").callsFake(function * () {
  yield 'fake name'
});

异步生成器也可以通过将其定义为async function *来伪造。

1
这是使用yield* [expression]co模块的单元测试解决方案。

file.ts:

export function* get(a) {
  yield "real data";
}

index.ts:

import * as name from "./file";
import co from "co";

export function* secondFunc(a, b, c) {
  try {
    const x = yield* name.get(a);
    return x;
  } catch (err) {
    console.error(err);
  }
}

export const func = (a, b, c) => co(secondFunc.bind(null, a, b, c));

index.spec.ts:

import { secondFunc, func } from "./";
import { expect } from "chai";
import * as name from "./file";
import sinon from "sinon";
import co from "co";

describe("59308604", () => {
  afterEach(() => {
    sinon.restore();
  });
  it("should pass secondFunc", () => {
    function* mGen() {
      yield "fake data";
    }
    const nameGetStub = sinon.stub(name, "get").returns(mGen());
    const gen = secondFunc("a", "b", "c");
    expect(gen.next().value).to.be.eql("fake data");
    expect(gen.next()).to.be.eql({ value: undefined, done: true });
    sinon.assert.calledWith(nameGetStub, "a");
  });

  it("should pass func", async () => {
    function* mGen() {
      return "fake data";
    }
    const nameGetStub = sinon.stub(name, "get").returns(mGen() as any);
    const actual = await func("a", "b", "c");
    expect(actual).to.be.equal("fake data");
    sinon.assert.calledWith(nameGetStub, "a");
  });

  it("test co", () => {
    function* g1() {
      return "123";
    }
    return co(function*() {
      var result = yield* g1();
      return result;
    }).then((value) => {
      expect(value).to.be.eql("123");
    });
  });
});

单元测试结果和覆盖率报告:

 59308604
    ✓ should pass secondFunc
    ✓ should pass func
    ✓ test co


  3 passing (17ms)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |    95.12 |    66.67 |    92.31 |    94.44 |                   |
 file.ts       |       50 |        0 |        0 |       50 |                 2 |
 index.spec.ts |      100 |      100 |      100 |      100 |                   |
 index.ts      |    88.89 |      100 |      100 |    85.71 |                 9 |
---------------|----------|----------|----------|----------|-------------------|

源代码:https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59308604


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