拦截器是 ts-axios 库一个非常实用的功能,接下来我们来编写它的测试代码。
测试代码编写
test/interceptor.spec.ts:
import axios, { AxiosRequestConfig, AxiosResponse } from '../src/index'import { getAjaxRequest } from './helper'describe('interceptors', () => {beforeEach(() => {jasmine.Ajax.install()})afterEach(() => {jasmine.Ajax.uninstall()})test('should add a request interceptor', () => {const instance = axios.create()instance.interceptors.request.use((config: AxiosRequestConfig) => {config.headers.test = 'added by interceptor'return config})instance('/foo')return getAjaxRequest().then(request => {expect(request.requestHeaders.test).toBe('added by interceptor')})})test('should add a request interceptor that returns a new config object', () => {const instance = axios.create()instance.interceptors.request.use(() => {return {url: '/bar',method: 'post'}})instance('/foo')return getAjaxRequest().then(request => {expect(request.method).toBe('POST')expect(request.url).toBe('/bar')})})test('should add a request interceptor that returns a promise', done => {const instance = axios.create()instance.interceptors.request.use((config: AxiosRequestConfig) => {return new Promise(resolve => {setTimeout(() => {config.headers.async = 'promise'resolve(config)}, 10)})})instance('/foo')setTimeout(() => {getAjaxRequest().then(request => {expect(request.requestHeaders.async).toBe('promise')done()})}, 100)})test('should add multiple request interceptors', () => {const instance = axios.create()instance.interceptors.request.use(config => {config.headers.test1 = '1'return config})instance.interceptors.request.use(config => {config.headers.test2 = '2'return config})instance.interceptors.request.use(config => {config.headers.test3 = '3'return config})instance('/foo')return getAjaxRequest().then(request => {expect(request.requestHeaders.test1).toBe('1')expect(request.requestHeaders.test2).toBe('2')expect(request.requestHeaders.test3).toBe('3')})})test('should add a response interceptor', done => {let response: AxiosResponseconst instance = axios.create()instance.interceptors.response.use(data => {data.data = data.data + ' - modified by interceptor'return data})instance('/foo').then(data => {response = data})getAjaxRequest().then(request => {request.respondWith({status: 200,responseText: 'OK'})setTimeout(() => {expect(response.data).toBe('OK - modified by interceptor')done()}, 100)})})test('should add a response interceptor that returns a new data object', done => {let response: AxiosResponseconst instance = axios.create()instance.interceptors.response.use(() => {return {data: 'stuff',headers: null,status: 500,statusText: 'ERR',request: null,config: {}}})instance('/foo').then(res => {response = res})getAjaxRequest().then(request => {request.respondWith({status: 200,responseText: 'OK'})setTimeout(() => {expect(response.data).toBe('stuff')expect(response.headers).toBeNull()expect(response.status).toBe(500)expect(response.statusText).toBe('ERR')expect(response.request).toBeNull()expect(response.config).toEqual({})done()}, 100)})})test('should add a response interceptor that returns a promise', done => {let response: AxiosResponseconst instance = axios.create()instance.interceptors.response.use(data => {return new Promise(resolve => {// do something asyncsetTimeout(() => {data.data = 'you have been promised!'resolve(data)}, 10)})})instance('/foo').then(res => {response = res})getAjaxRequest().then(request => {request.respondWith({status: 200,responseText: 'OK'})setTimeout(() => {expect(response.data).toBe('you have been promised!')done()}, 100)})})test('should add multiple response interceptors', done => {let response: AxiosResponseconst instance = axios.create()instance.interceptors.response.use(data => {data.data = data.data + '1'return data})instance.interceptors.response.use(data => {data.data = data.data + '2'return data})instance.interceptors.response.use(data => {data.data = data.data + '3'return data})instance('/foo').then(data => {response = data})getAjaxRequest().then(request => {request.respondWith({status: 200,responseText: 'OK'})setTimeout(() => {expect(response.data).toBe('OK123')done()}, 100)})})test('should allow removing interceptors', done => {let response: AxiosResponselet interceptconst instance = axios.create()instance.interceptors.response.use(data => {data.data = data.data + '1'return data})intercept = instance.interceptors.response.use(data => {data.data = data.data + '2'return data})instance.interceptors.response.use(data => {data.data = data.data + '3'return data})instance.interceptors.response.eject(intercept)instance.interceptors.response.eject(5)instance('/foo').then(data => {response = data})getAjaxRequest().then(request => {request.respondWith({status: 200,responseText: 'OK'})setTimeout(() => {expect(response.data).toBe('OK13')done()}, 100)})})})
运行测试后我们发现在测试用例 should add a request interceptor that returns a new config object 报错了,是代码运行的报错,而不是测试期望结果的报错,顺着报错信息,我们可以找到报错原因。
在 core/xhr.ts 中,执行到 processHeaders 中的 Object.keys(headers).forEach 代码报错,因为我们在拦截器对请求配置做了修改,导致 headers 为空,所以报错。
于是我们在解构赋值 headers 的时候,给它添加默认值即可。
const {// ...headers = {}} = config
再次运行测试,发现全部测试通过。
至此,我们完成了 ts-axios 库对拦截器模块的单元测试,下节课我们来测试 mergeConfig 模块的业务逻辑。
