首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用mocha、chai和robotjs测试需要用户在命令行中输入的功能?

如何使用mocha、chai和robotjs测试需要用户在命令行中输入的功能?
EN

Stack Overflow用户
提问于 2020-12-15 08:46:59
回答 1查看 577关注 0票数 0

我正在尝试使用mocha、chai和robotjs对此函数进行单元测试。我目前能够让robotjs输入数据,但我不能自己测试这个功能。现在我的终端显示我期望{}等于'https://toscrape.com/'‘。'https://toscrape.com/‘是此函数中使用的baseurl,如果用户键入no,则应返回此user。一个对象稍后会从另一个函数返回。如何测试此函数?

代码语言:javascript
复制
// allow user to input a url and then validate url
const requestSiteURL = async function () {
  let url = await new Promise((resolve) => {
    readline.question('Please type url: ', resolve);
  });
  let URL = 'https://toscrape.com/';
  if (validUrl.isUri(url)) {
    readline.close();
    return url;
  } else if (url.toLowerCase() === 'no') {
    url = URL;
    return url;
  } else {
    console.log(
      'Please type in a valid URL (https://toscrape.com/) or type "no" to use base url.'
    );
    return requestSiteURL();
  }
};

这是我到目前为止的测试用例

代码语言:javascript
复制
const url = require('../crawler');
const robot = require('robotjs');
var chai = require('chai');
var expect = chai.expect;

var roboInput = () => {
  robot.typeString('no');
  robot.keyTap('enter');
};

describe('validates site url', function () {
  it('no', function () {
    roboInput();
    let result = url.requestSiteURL();
    expect(result).to.equal('https://toscrape.com/');
  });
});
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-23 17:56:35

您希望编写单元测试,因此需要在隔离的、无副作用的环境中测试代码。为了提供这样的环境,有必要为具有副作用的模块和方法创建存根或模拟。这里我将使用sinon.js,因为它经常与mocha测试框架和chai断言库结合使用。

什么是隔离环境?对于您的示例,我们不需要用户或robotjs自动化脚本来真正在终端中输入文本。

对于您的情况,我们应该为readline.question()readline.close()等创建存根。

例如。

crawler.js

代码语言:javascript
复制
const rl = require('readline');

const validUrl = {
  isUri(url) {
    return url === 'https://toscrape.com/';
  },
};
const readline = rl.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const requestSiteURL = async function() {
  let url = await new Promise((resolve) => {
    readline.question('Please type url: ', resolve);
  });
  let URL = 'https://toscrape.com/';
  if (validUrl.isUri(url)) {
    readline.close();
    return url;
  } else if (url.toLowerCase() === 'no') {
    url = URL;
    return url;
  } else {
    console.log('Please type in a valid URL (https://toscrape.com/) or type "no" to use base url.');
    return requestSiteURL();
  }
};

module.exports = { requestSiteURL };

crawler.test.js

代码语言:javascript
复制
const chai = require('chai');
const sinon = require('sinon');
const readline = require('readline');
const expect = chai.expect;

function resetModules() {
  delete require.cache[require.resolve('./crawler')];
}

describe('65298539', () => {
  beforeEach(() => {
    resetModules();
  });
  afterEach(() => {
    sinon.restore();
  });
  it('should return url if it is valid', async () => {
    const readlineInterfaceStub = {
      question: sinon.stub().callsFake((query, callback) => {
        callback('https://toscrape.com/');
      }),
      close: sinon.stub(),
    };
    sinon.stub(readline, 'createInterface').returns(readlineInterfaceStub);
    const url = require('./crawler');
    const actual = await url.requestSiteURL();
    expect(actual).to.be.eql('https://toscrape.com/');
    sinon.assert.calledWithExactly(readlineInterfaceStub.question, 'Please type url: ', sinon.match.func);
    sinon.assert.calledOnce(readlineInterfaceStub.close);
  });

  it('should set default url if user enter "no"', async () => {
    const readlineInterfaceStub = {
      question: sinon.stub().callsFake((query, callback) => {
        callback('No');
      }),
    };
    sinon.stub(readline, 'createInterface').returns(readlineInterfaceStub);
    const url = require('./crawler');
    const actual = await url.requestSiteURL();
    expect(actual).to.be.eql('https://toscrape.com/');
    sinon.assert.calledWithExactly(readlineInterfaceStub.question, 'Please type url: ', sinon.match.func);
  });

  it('should recursive call', async () => {
    let callCount = 0;
    const readlineInterfaceStub = {
      question: sinon.stub().callsFake((query, callback) => {
        if (callCount === 0) {
          callCount++;
          callback('');
        } else {
          callback('No');
        }
      }),
    };
    sinon.stub(readline, 'createInterface').returns(readlineInterfaceStub);
    sinon.spy(console, 'log');

    const url = require('./crawler');
    const actual = await url.requestSiteURL();
    expect(actual).to.be.eql('https://toscrape.com/');
    sinon.assert.calledWithExactly(readlineInterfaceStub.question, 'Please type url: ', sinon.match.func);
    sinon.assert.calledWithExactly(
      console.log,
      'Please type in a valid URL (https://toscrape.com/) or type "no" to use base url.',
    );
  });
});

单元测试结果:

代码语言:javascript
复制
  65298539
    ✓ should return url if it is valid (1516ms)
    ✓ should set default url if user enter "no"
Please type in a valid URL (https://toscrape.com/) or type "no" to use base url.
    ✓ should recursive call


  3 passing (2s)

------------|---------|----------|---------|---------|-------------------
File        | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
------------|---------|----------|---------|---------|-------------------
All files   |     100 |      100 |     100 |     100 |                   
 crawler.js |     100 |      100 |     100 |     100 |                   
------------|---------|----------|---------|---------|-------------------
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65298539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档