首页 > 解决方案 > 一个接受第三方回调的方法的笑话模拟实现

问题描述

我正在使用 Nest + Cognito 对应用程序上的用户进行身份验证,我的身份验证服务中有一个方法,我正在尝试测试/模拟,它是:


async cognitoRegister(userPool: CognitoUserPool, {
    name,
    password,
    email
}: AuthRegisterInput): Promise < ISignUpResult > {
    return new Promise((resolve, reject) => {
        return userPool.signUp(
            name,
            password,
            [new CognitoUserAttribute({
                Name: 'email',
                Value: email
            })],
            null,
            (err, result) => {
                if (!result) {
                    reject(err);
                } else {
                    resolve(result);
                }
            },
        );
    });
}

这里的signUp函数是一个来自第三方 CognitoUserPool 的方法,我设法使用 package.json 中的模块名称映射器对其进行了模拟,这里是:

function CognitoUserPool(data) {
  const { UserPoolId, ClientId } = data;
  this.userPoolId = UserPoolId;
  this.clientId = ClientId;
  this.getCurrentUser = jest.fn().mockReturnValue("cognitouserpool");
  // This method
  this.signUp = jest.fn().mockReturnValue(true);
}
module.exports = CognitoUserPool;

并且是实施:

module.exports = {
  CognitoUserPool: jest.fn().mockImplementation(require("./CognitoUserPool")),
};

由于 signUp 方法接受一个回调,它负责给我一个结果/拒绝值,我应该以某种方式模拟它,否则 Jest 给我一个超时错误,因为实现返回一个保持在挂起状态的 Promise。

基本上我正在尝试模拟这种功能:


const foo = (arg1, cb) => {
    ...do something...
}

const bar = (arg1, arg2...) => {
    return new Promise((resolve, reject) => {
        return foo(arg1, (err, result) => {
            if (!result) {
                reject(err)
            } else {
                resolve(result)
            }
        })
    })
}

这是我在测试中尝试做的事情:

it("should register a cognito user", async () => {
  const mockedCongitoUserPool = new CognitoUserPool({
    UserPoolId: authConfig.userPoolId,
    ClientId: authConfig.clientId,
  });
  const result = await service.cognitoRegister(mockedCongitoUserPool, {
    ...mockedUser,
  });
  console.log(result);
});

我也有一个 git 可能会有所帮助:

主要服务链接

模拟第三方实现链接

测试实现链接

感谢这里的任何帮助<3,要求任何进一步的解释我真的需要一些帮助。

标签: javascripttypescriptunit-testingjestjsnestjs

解决方案


要获得静态解析,您的模拟模块应声明如下实现,而不仅仅是返回值:

this.signUp = jest.fn().mockImplementation((name, pwd, attlist, something, cb) => {
  process.nextTick(cb(null, 'signedup!'))
});

这里process.nextTick只是模拟异步,但cb(null, 'some result')如果您不在乎,也可以调用。

如果您想动态控制回调解析,您可以根据您的场景覆盖默认的模拟实现:

let cup: CognitoUserPool;
beforeAll(() => { // or maybe beforeEach, depends on what the mock keeps/does
  cup = new CognitoUserPool({ userPoolId: 'fakeUserPoolId', ClientId: 'fakeClientId' });
});
it('should resolve', async () => {
  const expected = { any: 'thing' };
  cup.signUp.mockImplementation((a, b, c, d, cb) => cb(null, expected));
  await expect(service.cognitoRegister(cup, mockedUser)).resolves.toBe(expected);
});
it('should fail', async () => {
  const expected = new Error('boom!');
  cup.signUp.mockImplementation((a, b, c, d, cb) => cb(expected));
  await expect(service.cognitoRegister(cup, mockedUser)).rejects.toThrow(expected);
});

推荐阅读