模拟在同一模块中导出和调用的模块函数?

Ren*_*nis 8 javascript testing unit-testing node.js sinon

新的单元测试和间谍,存根和嘲笑的概念.

我想从下面的代码中测试该verify方法password.js,但我无法在测试文件中使用stubhash函数.

由于verify采用了hash功能和hash性能输出,不过,我觉得我应该stubhash函数返回,而实际调用一个固定的响应hash.因为我不是想测试这个hash功能.

问题:hash测试时未调用创建的函数存根verify.

问题1:我应该专注于测试函数本身的逻辑而不是其他被称为函数的逻辑吗?

主要问题:(已 回答)如何在同一模块中调用模块函数?

问题2:hash如果它没有被导出但只留在模块中,我将如何进行存根?

password.js

/**
 * Creates a hash based on a salt from a given password
 * if there is no salt a new salt will be generated
 *
 * @param {String} password
 * @param {String} [salt] Optional value, if not given will generate a salt
 */
function hash (password, salt) {
  // returns a promise that resolves an hash object with hash and salt key
  // example: {hash: '2512521nska...', salt: '25hbBhhsfa...'}
}

/**
 * Verifies if a password matches a hash by hashing the password
 * with a given salt
 *
 * @param {String} password
 * @param {String} hashString
 * @param {String} salt
 */
function verify (password, hashString, salt) {
  return hash(password, salt)
    .then((res) => res.hash === hashString);
}

module.exports = {hash, verify};
Run Code Online (Sandbox Code Playgroud)

password.test.js

import test from 'ava';
import sinon from 'sinon';

import passwordModule from './password';

test('verify - should verify password', function * (t) {
  const password = 'test-password';
  const salt = null;
  const hash = 'my-hash';

  const hashStub = sinon.stub(passwordModule, 'hash', (password, salt) => Promise.resolve({hash, salt}));

  const verified = yield passwordModule.verify(password, hash, salt);

  t.true(verified);

  hashStub.restore();
});
Run Code Online (Sandbox Code Playgroud)

建立

  • 节点v6.2.0
  • Ava v0.15.2
  • 诗乃"v1.17.4

测试和模块用babel进行.但是该模块没有使用ES6模块导出,因为它在节点env中使用而没有进行转换.
我正在测试期间发布所有代码,以便它是未来的证明,并且save env可以用于前端代码和后端代码,前端代码在其中被传输.

rob*_*lep 7

问题1:我应该专注于测试函数本身的逻辑而不是其他被称为函数的逻辑吗?

测试的一部分verify是确保它hash正确调用.同样在更一般的意义上,并不是那么适用于您的代码,是一个函数应该正确处理其他函数抛出的错误.在您的情况下,您将任何错误传播给调用者verify,这就是它不适用的原因.

主要问题:如何在同一模块中调用模块函数?

您已经找到了答案,但请参阅下面的替代方案.

方面问题2:如果没有导出但仅保留在模块内,我将如何进行存根哈希?

一个很棒的模块是rewire,它允许您覆盖模块内的私有(非导出)变量.它也有助于你的"主要问题",因为它允许你像以前一样保留代码.

这是你对重新布线的测试:

import test   from 'ava';
import sinon  from 'sinon';
import rewire from 'rewire';

const passwordModule = rewire('./password');

test('verify - should verify password', function * (t) {
  const password = 'test-password';
  const salt = null;
  const hash = 'my-hash';

  let hashStub = sinon.stub().returns(Promise.resolve({hash, salt}));

  // Replace the `hash` function inside your module with the stub.
  let revert   = passwordModule.__set__('hash', hashStub);

  const verified = yield passwordModule.verify(password, hash, salt);

  t.true(verified);

  // Revert to the original `hash` function.
  revert();
});
Run Code Online (Sandbox Code Playgroud)


Ren*_*nis 2

找到了 stackoverflow 中主要问题的答案:
Stub module function Called from the same module

为了解决这个问题,我需要将哈希称为导出hash函数而不是私有函数。

exports.hash = function hash (password, salt) {
  // returns a promise that resolves an hash object with hash and salt key
  // example: {hash: '2512521nska...', salt: '25hbBhhsfa...'}
}

exports.verify = function verify (password, hashString, salt) {
  return exports.hash(password, salt)
    .then((res) => res.hash === hashString);
}
Run Code Online (Sandbox Code Playgroud)

还是想知道附带问题的答案。