请求取消模块单元测试
请求取消模块是 ts-axios
库核心流程其中一个分支,也是非常重要的模块,我们将从基础库和业务流程模块 2 个方面去编写单元测试。
Cancel 类单元测试
cancel/Cancel.spec.ts
:
import Cancel, { isCancel } from '../../src/cancel/Cancel'
describe('cancel:Cancel', () => {
test('should returns correct result when message is specified', () => {
const cancel = new Cancel('Operation has been canceled.')
expect(cancel.message).toBe('Operation has been canceled.')
})
test('should returns true if value is a Cancel', () => {
expect(isCancel(new Cancel())).toBeTruthy()
})
test('should returns false if value is not a Cancel', () => {
expect(isCancel({ foo: 'bar' })).toBeFalsy()
})
})
CancelToken 类单元测试
cancel/CancelToken.spec.ts
:
import CancelToken from '../../src/cancel/CancelToken' import Cancel from '../../src/cancel/Cancel' import { Canceler } from '../../src/types' describe('CancelToken', () => { describe('reason', () => { test('should returns a Cancel if cancellation has been requested', () => { let cancel: Canceler let token = new CancelToken(c => { cancel = c }) cancel!('Operation has been canceled.') expect(token.reason).toEqual(expect.any(Cancel)) expect(token.reason!.message).toBe('Operation has been canceled.') }) test('should has no side effect if call cancellation for multi times', () => { let cancel: Canceler let token = new CancelToken(c => { cancel = c }) cancel!('Operation has been canceled.') cancel!('Operation has been canceled.') expect(token.reason).toEqual(expect.any(Cancel)) expect(token.reason!.message).toBe('Operation has been canceled.') }) test('should returns undefined if cancellation has not been requested', () => { const token = new CancelToken(() => { // do nothing }) expect(token.reason).toBeUndefined() }) }) describe('promise', () => { test('should returns a Promise that resolves when cancellation is requested', done => { let cancel: Canceler const token = new CancelToken(c => { cancel = c }) token.promise.then(value => { expect(value).toEqual(expect.any(Cancel)) expect(value.message).toBe('Operation has been canceled.') done() }) cancel!('Operation has been canceled.') }) }) describe('throwIfRequested', () => { test('should throws if cancellation has been requested', () => { let cancel: Canceler const token = new CancelToken(c => { cancel = c }) cancel!('Operation has been canceled.') try { token.throwIfRequested() fail('Expected throwIfRequested to throw.') } catch (thrown) { if (!(thrown instanceof Cancel)) { fail('Expected throwIfRequested to throw a Cancel, but test threw ' + thrown + '.') } expect(thrown.message).toBe('Operation has been canceled.') } }) test('should does not throw if cancellation has not been requested', () => { const token = new CancelToken(() => { // do nothing }) token.throwIfRequested() }) }) describe('source', () => { test('should returns an object containing token and cancel function', () => { const source = CancelToken.source() expect(source.token).toEqual(expect.any(CancelToken)) expect(source.cancel).toEqual(expect.any(Function)) expect(source.token.reason).toBeUndefined() source.cancel('Operation has been canceled.') expect(source.token.reason).toEqual(expect.any(Cancel)) expect(source.token.reason!.message).toBe('Operation has been canceled.') }) }) })
注意,这里我们使用了fail
函数表示一个测试的失败,这个并未在 Jest 文档中体现,但它是一个可以用的 API。
Cancel 业务逻辑单元测试
cancel.spec.ts
:
import axios from '../src/index'
import { getAjaxRequest } from './helper'
describe('cancel', () => {
const CancelToken = axios.CancelToken
const Cancel = axios.Cancel
beforeEach(() => {
jasmine.Ajax.install()
})
afterEach(() => {
jasmine.Ajax.uninstall()
})
describe('when called before sending request', () => {
test('should rejects Promise with a Cancel object', () => {
const source = CancelToken.source()
source.cancel('Operation has been canceled.')
return axios
.get('/foo', {
cancelToken: source.token
})
.catch(reason => {
expect(reason).toEqual(expect.any(Cancel))
expect(reason.message).toBe('Operation has been canceled.')
})
})
})
describe('when called after request has been sent', () => {
test('should rejects Promise with a Cancel object', done => {
const source = CancelToken.source()
axios
.get('/foo/bar', {
cancelToken: source.token
})
.catch(reason => {
expect(reason).toEqual(expect.any(Cancel))
expect(reason.message).toBe('Operation has been canceled.')
done()
})
getAjaxRequest().then(request => {
source.cancel('Operation has been canceled.')
setTimeout(() => {
request.respondWith({
status: 200,
responseText: 'OK'
})
}, 100)
})
})
test('calls abort on request object', done => {
const source = CancelToken.source()
let request: any
axios
.get('/foo/bar', {
cancelToken: source.token
})
.catch(() => {
expect(request.statusText).toBe('abort')
done()
})
getAjaxRequest().then(req => {
source.cancel()
request = req
})
})
})
describe('when called after response has been received', () => {
test('should not cause unhandled rejection', done => {
const source = CancelToken.source()
axios
.get('/foo', {
cancelToken: source.token
})
.then(() => {
window.addEventListener('unhandledrejection', () => {
done.fail('Unhandled rejection.')
})
source.cancel()
setTimeout(done, 100)
})
getAjaxRequest().then(request => {
request.respondWith({
status: 200,
responseText: 'OK'
})
})
})
})
})
注意这里我们使用了 done.fail
表示了一个异常的结束,这个并未在 Jest 文档中体现,但它是一个可以用的 API。
至此,我们完成了取消模块相关业务逻辑的单元测试,我们测试覆盖率达到了阈值,测试已经通过了。但是扔未达到我们的目标,还有很多 feature 是没有覆盖到的。接下来我们就完成剩余 feature 的编写单元测试。
Pixivic : http://hxsm8080.com/