我想以最孤立的方式测试我所拥有的函数,返回一个已排序的数组,我所具有的函数具有这样的形状:
import factoryishFunction from './someModule'
import { times } from 'ramda';
export function generateArrayWith(nonDeterministicFunction, deterministicFunction, sizeOfArray) {
return times(factoryishFunction(nonDetermisticFunction, deterministicFunction), sizeOfArray)
.sort((a, b) => (a.value< b.value? 1 : -1)) }
所以基本上我调用times调用一个函数n次并将结果放在一个数组中。然后我调用这个factoryishFunction
,使用其他传递的函数返回一个具有属性值的对象,然后按后代顺序按值排序。 factoryishFunction的示例如下:
function factoryishFunction(nonDeterministicFunction, deterministicFunction) {
return deterministicFunction(nonDeterministicFunction)
}
其中nonDeterministicFunction可以是例如() => Math.random()
而确定性的(value) => value * 2
根据我的理解,由于factoryishFunction
正在做其他事情以便让我恢复价值,我应该在测试中嘲笑它以便进行真正独立的单元测试。
由于factoryishFunction
的结果取决于我传递给generateArrayWith
的函数,我怀疑的是,在我不涉及factoryishFunction
的情况下编写测试的最佳方法是什么?行为。
例如我有:
import generateArrayWith from '../ItsModule';
import factoryishFunctionMock from '../someModule';
jest.mock('../someModule');
beforeAll(() => {
factoryishFunctionMock .mockClear();
});
describe('My module', () => {
it('returns the values sorted', () => {
factoryishFunctionMock .mockImplementation((() => {
let value = 0;
return () => ({value: value++});
})); // Each call in the mockedImplementation will return a different value from zero and up
const noop = () => {};
const actual = generateArrayWith(noop, noop, 3);
expect(actual).toEqual([{value: 2},{value: 1},{value: 0},]);
});
});
但我觉得通过将noop
传递给generateArrayWith
,我不能断言这些值,因为它们依赖于传递的函数。我怎么能以更好的方式做到这一点?
答案 0 :(得分:1)
我认为你的一般方法很好。你可以添加的一件事就是不要为每个noop()
做同样的事情,给它两个不同的间谍。然后,您可以断言这些spys每次被称为正确的次数:
it('returns the values sorted', () => {
factoryishFunctionMock .mockImplementation(((nonDet, det) => {
nonDet();
det();
let value = 0;
return () => ({value: value++});
}));
const count = 3;
const nonDetSpy = jest.fn();
const detSpy = jest.fn();
const actual = generateArrayWith(nonDetSpy, detSpy, count);
expect(actual).toEqual([{value: 2},{value: 1},{value: 0},]);
expect(nonDetSpy).toHaveBeenCalledTimes(count);
expect(detSpy).toHaveBeenCalledTimes(count);
});
这应该允许您在不直接调用factoryishFunction()
的情况下测试函数的所有组件。
这仍然意味着你正在呼唤真实的times()
。如果你想让它真正成为一个单元测试,你可以改为模拟times()
并确保用factoryishFunctionMock
返回值调用它。
import { times } from 'ramda';
jest.mock('ramda'); // mock it to a simple spy in <project_root>/__mocks__/ramda.js
// ...
it('returns the values sorted', () => {
const factoryishFunctionMockResult = Symbol('RESULT'); // just something to compare against
times.mockImplementation(() => [{ value: 0 }, { value: 2 }, { value: 1 }];
factoryishFunctionMock.mockImplementation((() => factoryishFunctionMockResult);
const count = 3;
const nonDet = jest.fn();
const det = jest.fn();
const actual = generateArrayWith(nonDetSpy, detSpy, count);
expect(times).toHaveBeenCalledWith(factoryishMethodMockResult, count);
expect(factoryishMethodMock).toHaveBeenCalledWith(nonDet, det, count);
expect(actual).toEqual([{value: 2},{value: 1},{value: 0},]);
});