请求取消模块单元测试
大约 3 分钟约 825 字
请求取消模块单元测试
请求取消模块是 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 的编写单元测试。