用 axios 远程的请求数据。要使用 axios 就需要先进行安装,直接使用 npm 或 yarn 进行安装就可以了

npm install axios@0.19.0 --save

安装完成后,可以打开 package.json 看一下安装结果和版本,我这里使用的是 0.19.0 (如果你是其它版本,可能这个方法会出错,所以你最好和我使用一样的版本)。

# 异步代码的测试方法 - 1

一个异步请求地址 http://a.jspang.com/jestTest.json

安装好 axios 以后,在项目根目录下面,新建一个文件 fetchData.js 文件,然后编写代码如下:

import axios from 'axios'
export const fetchData = (fn)=>{
    axios.get('http://a.jspang.com/jestTest.json').then((response)=>{
        fn(response.data)
    })
}

测试文件 fetchData.test.js 在项目根目录下,新建一个 fetchData.test.js 文件

import { fetchData } from './fetchData.js'
test('fetchData 测试',()=>{
   fetchData((data)=>{
       expect(data).toEqual({
           success: true
       })
   })
  })

注意这样写是由问题的,因为方法还没有等到回调,我们的结果已经完成了,所以这时候你对于没测试完,只是方法可用,就返回了测试结果,这种结果是不保证正确的。

比如现在我们把请求的地址后边加一个 1, 这时候才测试,依然是正确的。

axios.get('http://a.jspang.com/jestTest1.json').then((response)=>{
        fn(response.data)
    })

所以我们必须加入一个 done 方法,保证我们的回调已经完成了,这时候我们表示测试完成。

import { fetchData } from './fetchData.js'
test('fetchData 测试',(done)=>{
   fetchData((data)=>{
       expect(data).toEqual({
           success: true
       })
       done()
   })
  })

# 异步代码的测试方法 - 2 直接返回 promise

还有一种方法式直接返回一个 promise 值,这样的方法在工作中也式经常使用的.

fetchData.js 文件,然后编写下面的代码:

export const fetchTwoData = ()=>{
    return axios.get('http://a.jspang.com/jestTest.json')
}

从代码中可以看出,我们直接只用了 Return 返回了异步请求的 promise 值,这样的方法在实际工作中也经常使用。

打开 fetchData.test.js 文件,然后新写一个测试用例,在写之前记得先把 fetchTwoData 方法引过来。

import { fetchData , fetchTwoData } from './fetchData.js'

引入之后,编写测试用例,代码如下:

test('FetchTwoData 测试', ()=>{
       return  fetchTwoData().then((response)=>{
            expect(response.data).toEqual({
                success: true
            })
        })
  })

这部分代码需要注意的是要使用 return 才能测试成功,这个坑我学习的时候也踩到了,所以给大家说一下,希望大家不要踩坑。

# 异步代码的测试方法 - 3 不存在接口的测试方法

后台需求不允许前台访问时,这时候就会返回 404(页面不存在),这时候在测试时也存在一些坑

继续打开 fetchData.test.js 文件,然后编写测试代码如下,注意这个地址是不存在的,也就是返回 404

export const fetchThreeData = ()=>{
    return axios.get('http://a.jspang.com/jestTest_error.json')
}

这时候可能很多小伙伴说测试 404 直接用 catch 就可以了,很简单,然后代码写成了这样。

test('FetchThreeData 测试', ()=>{
      return fetchThreeData().catch((e)=>{
        //console.log(e.toString())   
        expect(e.toString().indexOf('404')> -1).toBe(true)
      })
  })

但这样是错误的,比如现在我们把异步请求代码改正确后,我们再走一下测试,还是可以通过测试的。 现在把网址改成正确的:(http://a.jspang.com/jestTest.json)
那这是为什么那?因为测试用例使用了 catch 方法,也就是说只有出现异常的时候才会走这个方法,而现在没有出现异常,就不会走这个测试方法,Jest 就默认这个用例通过了测试。

这个也算是一个坑,想改这个坑也非常简单,只要使用 expect.assertions(1) 就可以了,这个代码的意思是 “断言,必须需要执行一次 expect 方法才可以通过测试”。

修改过后的代码就变成了这个样子

test('FetchThreeData 测试', ()=>{
      expect.assertions(1)  // 断言,必须执行一次 expect
      return fetchThreeData().catch((e)=>{
        expect(e.toString().indexOf('404')> -1).toBe(true)
      })
  })

这时候测试用例就无法正常通过测试了,因为此时我们的地址是存在并正确返回结果的。我们需要改成错误的地址,才能通过测试。(http://a.jspang.com/jestTest_error.json)

# 异步代码的测试方法 - 4async...await

上面异步测试用例时我使用了 return 的形式,这只是其中的一种方法,还有另一种方法,就是使用 async...await... 的这种语法形式来写测试用例。两种语法没有好坏之分,就看自己习惯和容易理解那种方法。

还是文件 fetchData.js 中,编写一个新的方法:

export const fetchFourData = ()=>{
    return axios.get('http://a.jspang.com/jestTest.json')
}

注意,这时候地址是正确的,也就是可以正常返回结果的。

# async...await 编写测试代码

这时候我们的代码使用 async....await... 的形式,这里我们还使用了 resolves 用于把现有对象转换成 Promise 对象,然后使用 Jest 中的 toMatchObject 进行匹配对象中的属性。

test('FetchFourData 测试', async()=>{
        //resolves 把现有对象转换成 Promise 对象,
        //toMatchObject 匹配对象中的属性
        await expect(fetchFourData()).resolves.toMatchObject({
            data:{
                success:true
            }
        })
})

写完上面的代码就可以出正确的结果了,但是这种方法还是有点抽象的,需要用 resolves 转换一下。有没有简单方法,答案是肯定的。我们可以把上面的测试方法写成这样。

test('FetchFourData 测试', async()=>{
        const response  = await fetchFourData()
        expect(response.data).toEqual({
            success : true
        })
})

这就是用 async...await... 来进行异步代码测试。