集成测试节点模块中的获取调用
Integration testing a fetch calls in a node module
目标: 调用一个调用 fetch 调用的函数以验证它是否适用于我的后端 rest-api(基本上是端到端测试)。
项目: 构建节点模块以导入到多个 React Web 应用程序中。该模块仅包含提取调用和最少的逻辑。它基本上是 URL 和设置的美化包装器。创建是为了减少实现应用程序中使用的通用端点所需的工作。
设置: 我有一个 docker 构建一个 docker 测试容器并拉入我的 rest-api docker 图像(建立在不同的系统中)。测试容器拉入打包模块并使用依赖项安装它。然后它会在后端和后端所需的其他图像(数据库、登录系统等)旁边显示测试。
问题:如何实施测试来处理调用。
目前我试过直接调用获取方法。这适用于我的登录提取,但任何其他调用都无法发送 cookie。据我了解,我拥有的代码取决于 cookie 的浏览器。我已经尝试了几种解决方案来获取所述 cookie,但我一直无法获取 node-fetch 以正确发送它。我最好的猜测是每个测试都在创建一个新的 cookie,但我缺乏完全调试此解决方案路径的知识。
我的发送解决方案路径是尝试使用 puppeteer 加载虚假页面,然后评估页面中的函数,例如:
https://github.com/puppeteer/puppeteer/issues/2579
问题是测试一直无法加载所需的库或其他一些问题。
代码:
这是我要测试的大部分调用。我拥有的每个函数都围绕着这个提供 {url: "api/endpoint/path", method: "GET"}。对于较大的数据帖子,有些人会传入 body。
export function request(options) {
//Build options
options = {
headers: {
'Content-Type': 'application/json'
},
...options
};
return fetch(options.url, options)
.then(response => {
//...
//Handle errors
if (!response.ok) {
return Promise.reject(`${response.status} - ${response.statusText}`);
}
try {
return response.json();
} catch (e) {
if (e.name === 'SyntaxError') {
return Promise.reject(response.text());
}
}
});
}
我试过的测试例子:
import puppeteer from "puppeteer";
import {myCall} from "my-rest-bridge";
it('Check response', async () => {
//Load browser
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox']
});
const page = await browser.newPage();
//Load page
await page.goto('http://docker:8888/index.html');
//Do login
expect(await page.evaluate(() => login('user', 'password')).toBe(expectedUserResponseJson);
//Make call
expect(await page.evaluate(() => myCall(input1, input2)).toBe(expectedCallResponseJson);
//Close page
await page.close();
})
花了我一段时间,但我为自己的问题构建了一个解决方案。它并不完美,所以如果有人有更好的想法请回答。
所以我的解决方案如下。我构建了一个附加 git 项目来在 docker 图像中创建一个 shell reactjs 应用程序。这个应用程序拉入我的节点模块,遍历所有导出,然后为每个函数生成一个组件。
import React from 'react';
import * as magicNodeModule from "magic-node-module"; //obviously not the real name
import CallRest from "./CallRest";
/** Core component for the application */
export default class App extends React.Component {
/** Renders the core application */
render() {
const restCalls = Object.keys(magicNodeModule);
return (
<div id={"App"}>
<div>
Functions found:
<ul id={"function-list"}>
{restCalls.map(restCall => <li>{restCall}</li>)}
</ul>
<hr/>
</div>
{
restCalls.map(restCall => {
return (
<CallRest restName={restCall} restCall={magicNodeModule[restCall]}/>
);
})
}
</div>
)
}
}
此组件 (CallRest) 包含输入框、提交按钮和输出 div。用户,或者在我的用例中是人偶操纵者,可以将数据输入到输入中。然后通过单击提交,它将 运行 提取调用并将结果输出插入 div。对于那些熟悉该系统的人来说,它的工作方式非常像 swagger 2。
该解决方案仍然构建为一系列 docker 图像在 compose 中。尽管它确实需要设置反向代理以允许 React 应用程序与后端通信 API。它还将节点模块的新副本作为压缩包拉入,并将其安装到 docker 中。这样我只需要构建 shell react docker 千载难逢。
目标: 调用一个调用 fetch 调用的函数以验证它是否适用于我的后端 rest-api(基本上是端到端测试)。
项目: 构建节点模块以导入到多个 React Web 应用程序中。该模块仅包含提取调用和最少的逻辑。它基本上是 URL 和设置的美化包装器。创建是为了减少实现应用程序中使用的通用端点所需的工作。
设置: 我有一个 docker 构建一个 docker 测试容器并拉入我的 rest-api docker 图像(建立在不同的系统中)。测试容器拉入打包模块并使用依赖项安装它。然后它会在后端和后端所需的其他图像(数据库、登录系统等)旁边显示测试。
问题:如何实施测试来处理调用。
目前我试过直接调用获取方法。这适用于我的登录提取,但任何其他调用都无法发送 cookie。据我了解,我拥有的代码取决于 cookie 的浏览器。我已经尝试了几种解决方案来获取所述 cookie,但我一直无法获取 node-fetch 以正确发送它。我最好的猜测是每个测试都在创建一个新的 cookie,但我缺乏完全调试此解决方案路径的知识。
我的发送解决方案路径是尝试使用 puppeteer 加载虚假页面,然后评估页面中的函数,例如:
https://github.com/puppeteer/puppeteer/issues/2579
问题是测试一直无法加载所需的库或其他一些问题。
代码:
这是我要测试的大部分调用。我拥有的每个函数都围绕着这个提供 {url: "api/endpoint/path", method: "GET"}。对于较大的数据帖子,有些人会传入 body。
export function request(options) {
//Build options
options = {
headers: {
'Content-Type': 'application/json'
},
...options
};
return fetch(options.url, options)
.then(response => {
//...
//Handle errors
if (!response.ok) {
return Promise.reject(`${response.status} - ${response.statusText}`);
}
try {
return response.json();
} catch (e) {
if (e.name === 'SyntaxError') {
return Promise.reject(response.text());
}
}
});
}
我试过的测试例子:
import puppeteer from "puppeteer";
import {myCall} from "my-rest-bridge";
it('Check response', async () => {
//Load browser
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox']
});
const page = await browser.newPage();
//Load page
await page.goto('http://docker:8888/index.html');
//Do login
expect(await page.evaluate(() => login('user', 'password')).toBe(expectedUserResponseJson);
//Make call
expect(await page.evaluate(() => myCall(input1, input2)).toBe(expectedCallResponseJson);
//Close page
await page.close();
})
花了我一段时间,但我为自己的问题构建了一个解决方案。它并不完美,所以如果有人有更好的想法请回答。
所以我的解决方案如下。我构建了一个附加 git 项目来在 docker 图像中创建一个 shell reactjs 应用程序。这个应用程序拉入我的节点模块,遍历所有导出,然后为每个函数生成一个组件。
import React from 'react';
import * as magicNodeModule from "magic-node-module"; //obviously not the real name
import CallRest from "./CallRest";
/** Core component for the application */
export default class App extends React.Component {
/** Renders the core application */
render() {
const restCalls = Object.keys(magicNodeModule);
return (
<div id={"App"}>
<div>
Functions found:
<ul id={"function-list"}>
{restCalls.map(restCall => <li>{restCall}</li>)}
</ul>
<hr/>
</div>
{
restCalls.map(restCall => {
return (
<CallRest restName={restCall} restCall={magicNodeModule[restCall]}/>
);
})
}
</div>
)
}
}
此组件 (CallRest) 包含输入框、提交按钮和输出 div。用户,或者在我的用例中是人偶操纵者,可以将数据输入到输入中。然后通过单击提交,它将 运行 提取调用并将结果输出插入 div。对于那些熟悉该系统的人来说,它的工作方式非常像 swagger 2。
该解决方案仍然构建为一系列 docker 图像在 compose 中。尽管它确实需要设置反向代理以允许 React 应用程序与后端通信 API。它还将节点模块的新副本作为压缩包拉入,并将其安装到 docker 中。这样我只需要构建 shell react docker 千载难逢。