我需要测试一个函数(example()
),它使用另一个函数(validateDataset
)。由于我只想测试example()
函数,我嘲笑validateDataset()
。
当然,每个测试都需要模拟函数的不同结果。但是如何为模拟函数设置不同的promise结果?在我下面显示的尝试中,模拟函数总是返回相同的值。
所以在这个例子中,我无法测试抛出的错误。
functions.js
import { validateDataset } from './helper/validation'
export async function example (id) {
const { docElement } = await validateDataset(id)
if (!docElement) throw Error('Missing content')
return docElement
}
functions.test.js
import { example } from './functions'
jest.mock('./helper/validation', () => ({
validateDataset: jest.fn(() => Promise.resolve({
docMain: {},
docElement: {
data: 'result'
}
}))
}))
describe('example()', () => {
test('should return object', async () => {
const result = await example('123')
expect(result.data).toBe('result')
})
test('should throw error', async () => {
const result = await example('123')
// How to get different result (`null`) in this test
// How to test for the thrown error?
})
})
答案 0 :(得分:2)
Jest模拟的好处是,你可以模拟整个模块,并且通过要求它的默认或命名导出,你仍然可以得到一个模拟,你可以实现和重新实现,无论你喜欢什么
我发布了一个预期validateDataset
调用失败的测试示例实现。为简洁起见,我也留下了一些评论。
import { example } from './example';
import { validateDataset } from './helper/validation';
// Declare export of './helper/validation' as a Mock Function.
// It marks all named exports inside as Mock Functions too.
jest.mock('./helper/validation');
test('example() should return object', async () => {
// Because `validateDataset` is already mocked, we can provide
// an implementation. For this test we'd like it to be original one.
validateDataset.mockImplementation(() => {
// `jest.requireActual` calls unmocked module
return jest.requireActual('./helper/validation').validateDataset();
});
const result = await example('123');
expect(result.data).toBe('result');
});
test('example() should throw error', async () => {
// Worth to make sure our async assertions are actually made
expect.assertions(1);
// We can adjust the implementation of `validateDataset` however we like,
// because it's a Mock Function. So we return a null `docElement`
validateDataset.mockImplementation(() => ({ docElement: null }));
try {
await example('123');
} catch (error) {
expect(error.message).toEqual('Missing content');
}
});
希望能解决问题。
答案 1 :(得分:0)
您可以使用Rewire更改function.js
内的变量。
functions.test.js看起来像:
import * as rewire from 'rewire';
const functionsModule = rewire('functions.js');
describe('example()', () => {
var functionsModule;
test('should return object', done => {
functionsModule.__set__('validateDataset', () => {
Promise.resolve({
docMain: {},
docElement: {
data: 'result'
}
})
});
functionsModule.example('123').then(result => {
expect(result.docElement.data).toBe('result');
done();
});
})
test('should throw error', done => {
functionsModule.__set__('validateDataset', () => {
return Promise.reject();
});
functionsModule.example('123').catch(done);
});
})