gpt4 book ai didi

javascript - Node中功能测试代码的抽象

转载 作者:搜寻专家 更新时间:2023-10-31 23:50:32 25 4
gpt4 key购买 nike

我很难理解返回函数的函数,这些函数接受一个参数并将函数应用于它返回更多函数。或类似的东西。我的头很痛。

我有以下代码:

const app = require('../app'); // an express.js instance
const request = require('supertest');
const cheerio = require('cheerio'); // html parser and jquery selector engine

const html = assertion => response => assertion(cheerio.load(response.text));
const node = selector => html($ => {
const nodeset = $(selector);
if (nodeset.length === 0)
throw new Error('Expected "' + selector + '" to match at least 1 node, but it matched 0.');
});
const anyTextNode = (selector, value) => html($ => {
const nodeset = $(selector);
if (nodeset.filter((index, element) => element.children[0].type === 'text' && element.children[0].data === value).length === 0)
throw new Error('Expected "' + selector + '" to match at least 1 node containing "' + value + '", but found 0.');
});

describe('index route', () => {
describe('html representation', () => {
it('should display a search form', (done) => {
request(app).get('/')
.expect(node('form>input[type=search][name=q]'))
.expect(node('form>button[type=submit]'))
.end(done);
});
it('should display a list of links', (done) => {
request(app).get('/')
.expect(anyTextNode('body>h2', 'Links'))
.expect(node('ul>li>a[rel="http..."][href][href!=""]:not(:empty)'))
.end(done);
});

前两个期望独立测试是否有一个输入字段和一个按钮,并且每个都是表单的子元素,但它无法检查这两个元素是否是相同表单的子元素。如果 DOM 的形式是 <form><input/></form></form><button/></form>,它仍然会通过。 .
后两个期望检查是否存在标题和包含非空 href 的非空 anchor 元素的列表。它不会检查列表是否紧跟在标题之后,如果我检查“h2+ul”,则无法证明这是同一个 UL。

因此,我想添加一个允许我构建复合测试的新函数:首先从给定的选择器获取 Node 列表,然后执行其他类似 jQuery 的操作,因此在第一个示例中它将采用“表单”选择器然后检查它是否有这两个 child 。在第二个示例中,它将测试是否存在具有给定文本 Node 子 Node 的 H2,后跟 UL,并且该 UL 的子 Node 是有效链接。

当我尝试抽象像 node 这样的函数时,困难就来了和 anyTextNode (其中有很多)以减少重复。他们都叫html()并将执行检查的函数传递给它。调用html()的函数然后将 return 传递给 super 测试 expect()调用,它使用我正在测试的服务器的响应来调用它。我看不到可以使用的好的设计模式。

最佳答案

假设您有一个应用

const app = express();

它有一个get方法

app.get('/', method );

Controller 的职责应该是用一些数据调用(例如)template.render

const template = require('../path/to/templateEngine');
const method = (req, res) => {
const data = { a: 1 };
res.send(template.render('path/to/desided/template.ext', data));
}

它的职责是不返回特定标记,因此在您的测试中您可以模拟模板(因为它是一个依赖项)

const template = require('../path/to/template');
template.render = // some spy jest.fn() or sinon.mock() or chai.spy()

describe('method', () => {
it('should call the templateEngine.render to render the desired template', () => {
request(app).get('/');
// the template might even be an external dependency
expect(template.render)
.toBeCalledWith('path/to/desired/template.ext', { a: 1 });
})
})

然后单独测试模板;

const template = require('../path/to/templateEngine');
const cheerio = require('cheerio')

describe('template' => {
describe('given some mock data', () => {
const mockData = { /* some mock data */ }
it('should render the template with mocked data', () => {
expect(template.render('path/to/desired/template.ext', mockData))
});
});
// and here in the template specification it will be much cleaner
// to use cheerio
describe('form>button', () => {
const $ = cheerio.load(template.render('path/to/desired/template.ext', mockData));
it('to have exactly one submit button', () => {
expect($('form>button[type=submit]')).toHaveLength(1);
});
});
});

编辑:

考虑到它是一个模板测试,你可以这样写(未测试)

const cheerio = require('cheerio');
const request = require('supertest');
// template will be Promise<response>
const template = request(app).get('/')

describe('template', () => {
// if $ is the result from cheerio.load
// cherrioPromise will be Promise<$>
// and you can use $.find('selector') to write your assertions
const cheerioPromise = template.then(response => cheerio.load(response.text()))
it("should display a search form", () => {
// you should be able to return promise instead of calling done
return cheerioPromise.then($ => {
expect($.find('form>input[type=search][name=q]')).toHaveLength(1);
expect($.find('form>button[type=submit]')).toHaveLength(1)
})
});
it('should display a list of links', () => {
return cheerioPromise.then($ => {
expect($.find('ul>li>a[rel="http..."][href][href!=""]:not(:empty)')) /// some expectation
});
});
it('should have h2 with text "Links"', () => {
return cheerioPromise.then($ => {
expect($.find('body.h2').text()).toEqual('Links');
})
})
});

关于javascript - Node中功能测试代码的抽象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51967074/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com