我已经阅读了有关Jest的每一个SO问题和文档的每一个片段,但是我仍然不知道为什么Jest似乎根本不使用我的模拟实现。
我不确定是否应遵循模拟ES6类的说明。 XMLHttpRequest是窗口对象的方法,而不是真正的类,而类只是返回对象的函数,因此XMLHttpRequest毕竟是类。
由于我想共享我的模拟,所以我认为它适合手动模拟的模式,除了XMLHttpRequest不是模块,而且看起来手动模拟仅适用于模块。
这就是我写的模拟:
function mainMock() {
let readyState = 4;
let status = 200;
let statusText = 'OK';
let responseText = 'mocked data';
let response = {};
let error = null;
const open = jest.fn();
const onreadystatechange = jest.fn();
const send = jest.fn(function send() {
if (error) throw error;
this.onreadystatechange();
});
const addEventListener = jest.fn(function addEventListener(e, c) {
this.onreadystatechange = c;
});
function setStatus(newStatus = 200, newStatusText = 'OK', newReadyState = 4) {
status = newStatus;
statusText = newStatusText;
readyState = newReadyState;
}
function setResponseText(newResponseText) {
responseText = newResponseText;
response = {};
}
function setResponse(newResponse) {
responseText = JSON.stringify(newResponse);
response = newResponse;
}
function setError(newError) {
error = newError;
}
function cleanUp() {
if (window.XMLHttpRequest) {
delete window.XMLHttpRequest;
}
}
// mock constructor that will replace window XMLHttpRequest
function mockConstructor() {
return {
readyState,
status,
statusText,
responseText,
response,
open,
onreadystatechange,
addEventListener,
send,
};
}
// override/define XMLHttpRequest
window.XMLHttpRequest = mockConstructor;
return {
open,
onreadystatechange,
addEventListener,
cleanUp,
setStatus,
setResponseText,
setResponse,
setError,
send,
};
}
export default mainMock;
这是我的(缩写)单元测试
import XMLHttpRequestMock from '~mocks/XMLHttpRequestMock';
import { Service } from './Service';
let mockXMLHttpRequest;
beforeEach(() => {
mockXMLHttpRequest = XMLHttpRequestMock();
});
afterEach(() => {
mockXMLHttpRequest.cleanUp();
});
describe('Service', () => {
it('should-ping', async () => {
mockXMLHttpRequest.setResponse({
meta: { version: 99 },
data: {},
});
const service = new Service();
const meta = await service.ping();
expect(mockXMLHttpRequest.open).toHaveBeenCalled();
expect(mockXMLHttpRequest.send).toHaveBeenCalled();
expect(meta.version).toEqual(99);
expect(meta.status).toEqual(200);
});
});
我正在测试的类肯定会调用open
和send
方法,因为它实际上可以工作并从服务器中提取数据,但是expect(mockXMLHttpRequest.open)
失败了,因此所有其他expect
个电话(如果我放在第一位)。看来Jest根本根本没有使用该模拟。
我从这里去哪里?
为使图片更加完整,这是我正在测试的课程的简化版本。
import configVars from '~config/configVars';
import 'regenerator-runtime/runtime.js';
export class Service {
constructor(logger) {
this.logger = logger || console;
}
_getJson(request) {
const _this = this;
return new Promise(function(resolve, reject) {
var xhttp = new XMLHttpRequest();
xhttp.responseType = request.responseType || 'json';
xhttp.onreadystatechange = function() {
if (xhttp.readyState === XMLHttpRequest.DONE) {
if (this.status >= 200 && this.status < 300) {
resolve(this);
} else {
let e = {
status: this.status,
statusText: this.statusText,
};
reject(e);
}
}
};
let url = configVars.service.url + request.url;
xhttp.open('GET', url, true);
xhttp.setRequestHeader('Accept', request.accept || 'application/json');
try {
xhttp.send();
} catch (e) {
reject(e);
}
});
}
async ping() {
try {
let xhttp = await this._getJson({ url: 'ping' });
let meta = xhttp.response.meta;
meta.status = xhttp.status;
meta.statusText = xhttp.statusText;
return meta;
} catch (e) {
e.messages = e.messages || [];
e.messages.push('Ping of service failed');
return e;
}
}
}
export default Service;
答案 0 :(得分:0)
经过大量的摸索并试图弄清楚如何使VS Code调试器通过Jest测试,我终于将其归结为一个非常简单的东西。
我没有模拟setRequestHeader
,这导致我的类在调用send
方法之前引发了异常。