RxJS:如何用诺克测试 Observable.ajax() ?
RxJS: How to test Observable.ajax() with nock?
我目前正在学习 RxJS,我正在尝试弄清楚如何使用 nock
来测试 Observable.ajax()
。
这是我的简化示例,没有任何断言...我只是想看看 nock
是否可以拦截 API 调用。
import { afterEach, describe, it } from 'mocha';
import nock from 'nock';
import { ajax } from 'rxjs/observable/dom/ajax';
// had to use `crossDomain: true` for it to work in production code
const api = ajax({
url: 'https://server.com/abc',
crossDomain: true,
});
describe('ajax', () => {
afterEach(() => {
nock.cleanAll();
});
it('given valid call, should return value', (done) => {
nock('https://server.com', {
// needed to prevent "cross origin null forbidden" error
reqheaders: {
'Access-Control-Allow-Origin': '*',
},
}).get('/abc').reply(200, 'YAY!');
api
.map(e => e.json())
.subscribe(
value => console.log('SUCCESS', value),
error => console.log('ERROR', error),
() => done(),
);
});
});
执行上述代码时,我无法获得预期值 ("YAY!")。
相反,我得到了这个错误:-
Error: Error: Nock: No match for request {
"method": "GET",
"url": "https://server.com/abc",
"headers": {
"referer": "about:blank",
"user-agent": "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.2.0",
"accept-language": "en",
"accept": "*/*",
"origin": "null",
"host": "server.com",
"accept-encoding": "gzip, deflate"
}
}
subscribe(..)
上的 console.log(..)
显示:-
ERROR { [Error: ajax error]
message: 'ajax error',
xhr:
XMLHttpRequest {
upload: XMLHttpRequestUpload { _ownerDocument: [Object] },
_eventHandlers: { readystatechange: [Object] },
[Symbol(flag)]:
{ synchronous: false,
withCredentials: false,
mimeType: null,
auth: null,
method: 'GET',
responseType: 'json',
requestHeaders: {},
referrer: 'about:blank',
uri: 'https://server.com/abc',
timeout: 0,
body: undefined,
formData: false,
preflight: false,
requestManager: [Object],
pool: undefined,
agentOptions: undefined,
strictSSL: undefined,
proxy: undefined,
cookieJar: [Object],
encoding: 'UTF-8',
origin: 'null',
userAgent: 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.2.0' },
[Symbol(properties)]:
{ beforeSend: false,
send: false,
timeoutStart: 0,
timeoutId: 0,
timeoutFn: null,
client: [Object],
responseHeaders: {},
filteredResponseHeaders: [],
responseBuffer: null,
responseCache: null,
responseTextCache: null,
responseXMLCache: null,
responseURL: '',
readyState: 4,
status: 0,
statusText: '',
error: [Object],
uploadComplete: true,
uploadListener: false,
abortError: false,
cookieJar: [Object],
bufferStepSize: 1048576,
totalReceivedChunkSize: 0,
requestBuffer: null,
requestCache: null,
origin: 'null' } },
request:
{ async: true,
createXHR: [Function: createXHR],
crossDomain: true,
withCredentials: false,
headers: {},
method: 'GET',
responseType: 'json',
timeout: 0,
url: 'https://server.com/abc',
body: undefined },
status: 0 }
我的问题是如何配置 nock
以正确拦截 API 调用?
有没有更好的方法可以在不使用 nock
的情况下测试 API 调用?
谢谢。
我明白了。关键是在初始化JSDOM
.
时定义匹配被测API的url
这是带有断言的工作版本:-
import { afterEach, describe, it } from 'mocha';
import nock from 'nock';
import { expect } from 'chai';
import { ajax } from 'rxjs/observable/dom/ajax';
import { JSDOM } from 'jsdom';
// defining `url` is important!!
const { window } = new JSDOM('', { url: 'https://server.com' });
const apiUnderTest = ajax({
url: 'https://server.com/abc',
crossDomain: true,
createXHR: () => new window.XMLHttpRequest(),
});
describe('ajax', () => {
const expectedValue = 'YAY!';
afterEach(() => {
nock.cleanAll();
});
it('given successful call, should return value', (done) => {
nock('https://server.com').get('/abc').reply(200, { value: expectedValue });
apiUnderTest
.map(e => e.response.value)
.subscribe(
(actualValue) => {
expect(actualValue).to.deep.equal(expectedValue);
done();
},
(error) => {
expect(error).to.be.an('undefined');
done();
},
);
});
it('given failed call, should not return value', (done) => {
nock('https://server.com').get('/abc').reply(400, { value: expectedValue });
apiUnderTest
.map(e => e.response.value)
.subscribe(
(actualValue) => {
expect.fail(actualValue, undefined, 'Should not have value');
done();
},
(error) => {
expect(error).to.not.be.an('undefined');
done();
},
);
});
});
我目前正在学习 RxJS,我正在尝试弄清楚如何使用 nock
来测试 Observable.ajax()
。
这是我的简化示例,没有任何断言...我只是想看看 nock
是否可以拦截 API 调用。
import { afterEach, describe, it } from 'mocha';
import nock from 'nock';
import { ajax } from 'rxjs/observable/dom/ajax';
// had to use `crossDomain: true` for it to work in production code
const api = ajax({
url: 'https://server.com/abc',
crossDomain: true,
});
describe('ajax', () => {
afterEach(() => {
nock.cleanAll();
});
it('given valid call, should return value', (done) => {
nock('https://server.com', {
// needed to prevent "cross origin null forbidden" error
reqheaders: {
'Access-Control-Allow-Origin': '*',
},
}).get('/abc').reply(200, 'YAY!');
api
.map(e => e.json())
.subscribe(
value => console.log('SUCCESS', value),
error => console.log('ERROR', error),
() => done(),
);
});
});
执行上述代码时,我无法获得预期值 ("YAY!")。
相反,我得到了这个错误:-
Error: Error: Nock: No match for request {
"method": "GET",
"url": "https://server.com/abc",
"headers": {
"referer": "about:blank",
"user-agent": "Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.2.0",
"accept-language": "en",
"accept": "*/*",
"origin": "null",
"host": "server.com",
"accept-encoding": "gzip, deflate"
}
}
subscribe(..)
上的 console.log(..)
显示:-
ERROR { [Error: ajax error]
message: 'ajax error',
xhr:
XMLHttpRequest {
upload: XMLHttpRequestUpload { _ownerDocument: [Object] },
_eventHandlers: { readystatechange: [Object] },
[Symbol(flag)]:
{ synchronous: false,
withCredentials: false,
mimeType: null,
auth: null,
method: 'GET',
responseType: 'json',
requestHeaders: {},
referrer: 'about:blank',
uri: 'https://server.com/abc',
timeout: 0,
body: undefined,
formData: false,
preflight: false,
requestManager: [Object],
pool: undefined,
agentOptions: undefined,
strictSSL: undefined,
proxy: undefined,
cookieJar: [Object],
encoding: 'UTF-8',
origin: 'null',
userAgent: 'Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/11.2.0' },
[Symbol(properties)]:
{ beforeSend: false,
send: false,
timeoutStart: 0,
timeoutId: 0,
timeoutFn: null,
client: [Object],
responseHeaders: {},
filteredResponseHeaders: [],
responseBuffer: null,
responseCache: null,
responseTextCache: null,
responseXMLCache: null,
responseURL: '',
readyState: 4,
status: 0,
statusText: '',
error: [Object],
uploadComplete: true,
uploadListener: false,
abortError: false,
cookieJar: [Object],
bufferStepSize: 1048576,
totalReceivedChunkSize: 0,
requestBuffer: null,
requestCache: null,
origin: 'null' } },
request:
{ async: true,
createXHR: [Function: createXHR],
crossDomain: true,
withCredentials: false,
headers: {},
method: 'GET',
responseType: 'json',
timeout: 0,
url: 'https://server.com/abc',
body: undefined },
status: 0 }
我的问题是如何配置 nock
以正确拦截 API 调用?
有没有更好的方法可以在不使用 nock
的情况下测试 API 调用?
谢谢。
我明白了。关键是在初始化JSDOM
.
url
这是带有断言的工作版本:-
import { afterEach, describe, it } from 'mocha';
import nock from 'nock';
import { expect } from 'chai';
import { ajax } from 'rxjs/observable/dom/ajax';
import { JSDOM } from 'jsdom';
// defining `url` is important!!
const { window } = new JSDOM('', { url: 'https://server.com' });
const apiUnderTest = ajax({
url: 'https://server.com/abc',
crossDomain: true,
createXHR: () => new window.XMLHttpRequest(),
});
describe('ajax', () => {
const expectedValue = 'YAY!';
afterEach(() => {
nock.cleanAll();
});
it('given successful call, should return value', (done) => {
nock('https://server.com').get('/abc').reply(200, { value: expectedValue });
apiUnderTest
.map(e => e.response.value)
.subscribe(
(actualValue) => {
expect(actualValue).to.deep.equal(expectedValue);
done();
},
(error) => {
expect(error).to.be.an('undefined');
done();
},
);
});
it('given failed call, should not return value', (done) => {
nock('https://server.com').get('/abc').reply(400, { value: expectedValue });
apiUnderTest
.map(e => e.response.value)
.subscribe(
(actualValue) => {
expect.fail(actualValue, undefined, 'Should not have value');
done();
},
(error) => {
expect(error).to.not.be.an('undefined');
done();
},
);
});
});