【自动化测试】【Jest-Selenium】(03)—— Jest 异步测试

时间:2022-07-26
本文章向大家介绍【自动化测试】【Jest-Selenium】(03)—— Jest 异步测试,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1. 异步测试哪里特殊?

在JavaScript中执行异步代码是很常见的。当你有以异步方式运行的代码时,Jest 需要知道当前它测试的代码是否已完成,然后它可以转移到另一个测试。

经典错误:

  • 默认情况下,Jest 测试一旦执行到末尾就会完成。
    • 问题在于一旦 fetchData 执行结束,此测试就在没有调用回调函数前结束。
function fetchData(callback) {
    setTimeout(() => callback('peanut butter'), 5 * 1000);
}

// 经典错误
test('the data is peanut butter', () => {
    function callback(data) {
        expect(data).toBe('peanut butter');
    }
    fetchData(callback);
});

2. 异步测试基本模式

2.1. test('...', (done) => {...}) 模式

  • Jest will wait if you provide an argument to the test function, usually called done.
    • 默认测试超时时间:5s
      • 可通过 testTimeout 选项配置
function fetchData(callback) {
    setTimeout(() => callback('peanut butter'), 5 * 1000);
}

test('the data is peanut butter', (done) => {
    function callback(data) {
        expect(data).toBe('peanut butter');
        done();
    }
    fetchData(callback);
});

2.2. Promise 模式

  • If a promise is returned from test, Jest will wait for the promise to resolve before letting the test complete.
function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve('peanut butter'), 5 * 1000);
    });
}

test('the data is peanut butter', () => {
    return fetchData().then((data)=>{
        expect(data).toBe('peanut butter');
    });
});

2.3. Async|Await 模式

  • Alternatively, you can use async and await in your tests.
function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve('peanut butter'), 5 * 1000);
    });
}

test('the data is peanut butter', async () => {
    const data = await  fetchData();
    expect(data).toBe('peanut butter');
});

3. expect.hasAssertions()、expect.assertions(number)

观察一个例子:

function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve('peanut butter'), 5 * 1000);
    });
}

test('the data is peanut butter', async () => {
    try {
        await fetchData();
    } catch (e) {
        expect(e).toMatch('error');
    }
});

这个例子中,显然,代码不会运行到 "expect(e).toMatch('error')",但测试用例还是通过了,这显然不是我们想要的。

  • expect.hasAssertions()
    • expect.hasAssertions() verifies that at least one assertion is called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called.
  • expect.assertions(number)
    • expect.assertions(number) verifies that a certain number of assertions are called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called.

修改一下例子:

function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve('peanut butter'), 5 * 1000);
    });
}

test('the data is peanut butter', async () => {
    expect.hasAssertions(); // 划重点
    try {
        await fetchData();
    } catch (e) {
        expect(e).toMatch('error');
    }
});

再观察一个例子:

function doAsync(callback1, callback2) {
    callback1(true);
}

test('the data is peanut butter', async () => {
    expect.assertions(2); // 划重点

    function callback1(data) {
        expect(data).toBeTruthy();
    }
    function callback2(data) {
        expect(data).toBeTruthy();
    }

    doAsync(callback1, callback2);
});

4. .resolves、.rejects

  • Use resolves to unwrap the value of a fulfilled promise so any other matcher can be chained. If the promise is rejected the assertion fails.
  • Use .rejects to unwrap the reason of a rejected promise so any other matcher can be chained. If the promise is fulfilled the assertion fails.

示例1:

function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve('peanut butter'), 6 * 1000);
    });
}

test('the data is peanut butter', () => {
    return expect(fetchData()).resolves.toBe('peanut butter');
});

示例2:

function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(new Error('peanut butter'));
        }, 3 * 1000);
    });
}

test('the data is peanut butter', async () => {
    return expect(fetchData()).rejects.toThrow("peanut butter");
});

示例3:

function fetchData() {
  return new Promise((resolve, reject) => {
      setTimeout(() => {
          resolve(1);
      }, 3 * 1000);
  }).then(()=>{
    throw new Error('peanut butter');
  });
}

test('the data is peanut butter', () => {
  return expect(fetchData()).rejects.toThrow("peanut butter");
});

参考:

Jest Matchers: https://jestjs.io/docs/en/using-matchers Jest Expect API: https://jestjs.io/docs/zh-Hans/expect An Async Example: https://jestjs.io/docs/en/tutorial-async