拦截器模块单元测试
拦截器是 ts-axios
库一个非常实用的功能,接下来我们来编写它的测试代码。
测试代码编写
test/interceptor.spec.ts
:
typescript
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: AxiosResponse
const 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: AxiosResponse
const 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: AxiosResponse
const instance = axios.create()
instance.interceptors.response.use(data => {
return new Promise(resolve => {
// do something async
setTimeout(() => {
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: AxiosResponse
const 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: AxiosResponse
let intercept
const 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)
})
})
})
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: AxiosResponse
const 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: AxiosResponse
const 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: AxiosResponse
const instance = axios.create()
instance.interceptors.response.use(data => {
return new Promise(resolve => {
// do something async
setTimeout(() => {
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: AxiosResponse
const 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: AxiosResponse
let intercept
const 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
的时候,给它添加默认值即可。
typescript
const {
// ...
headers = {}
} = config
const {
// ...
headers = {}
} = config
再次运行测试,发现全部测试通过。
至此,我们完成了 ts-axios
库对拦截器模块的单元测试,下节课我们来测试 mergeConfig
模块的业务逻辑。