Bob*_*erg 6 javascript mocking jestjs
我有一些代码,我在构造函数中创建 PerformanceObserver,我试图弄清楚如何模拟它,以便我可以断言observe在观察者上调用的两个,并模拟正在生成的性能条目,这将导致回调被调用,并断言回调实际上被调用了。构造函数中的代码如下所示:
const { _tracking } = props;
this.resourceObserver = new PerformanceObserver((list) => {
const resourceEntries = list.getEntriesByType(
'resource',
) as PerformanceResourceTiming[];
for (const resource of resourceEntries) {
resourceObserverCallback(_tracking, resource);
}
performance.clearResourceTimings();
});
this.resourceObserver.observe({ entryTypes: ['resource'] });
Run Code Online (Sandbox Code Playgroud)
有没有人有什么建议?
编辑:
我可以observe通过创建一个createResourceObserver返回传入的 mock 或 real的函数来断言在观察者上调用它PerformanceObserver,这解决了部分问题,但我仍然不确定如何在测试中使用观察者。
下面是这个函数的样子:
createResourceObserver() {
const { _mockObserver, _tracking } = this.props;
if (_mockObserver) {
return _mockObserver;
}
const observer = new PerformanceObserver((list) => {
const resourceEntries = list.getEntriesByType(
'resource',
) as PerformanceResourceTiming[];
for (const resource of resourceEntries) {
resourceObserverCallback(_tracking, resource);
}
performance.clearResourceTimings();
});
return observer;
}
Run Code Online (Sandbox Code Playgroud)
小智 0
这需要一个很长的答案。工作游乐场示例链接位于最后。
要测试某些内容,您必须从外部隔离并注入所有外部依赖项。有不同的模式可以做到这一点。
您想要测试两件事 - 构造函数中发生的情况以及启动回调时发生的情况。我们将分别解决这些问题。要测试您的PerformanceObserverCallbackHandler,您需要将其分离可调用的东西,并注入所有外部依赖项。
我们将隔离并隐藏 PerformanceObserver 在单例工厂后面,以便我们可以控制注入哪个实现以及何时注入。
这是工厂的实现
class PerformanceObserverFactory {
private instance: PerformanceObserver | undefined;
create(callBack: PerformanceObserverCallback): PerformanceObserver {
if (this.instance) {
return this.instance;
}
return new PerformanceObserver(callBack);
}
setMockedIsntance(mock: PerformanceObserver) {
if (this.instance !== undefined) {
throw new Error(
'Mocked instance is already set. Consider calling reset() in beforeEach()'
);
}
this.instance = mock;
}
reset() {
this.instance = undefined;
}
}
const instance = new PerformanceObserverFactory();
export default instance;
Run Code Online (Sandbox Code Playgroud)
现在,让我们拆开班级。一些外部依赖项没有被描述,所以我伪造了它们。看declare global部分。这是消费者类的实现
import PerformanceObserverFactory from './PerformanceObserverFactory';
export type Handler = (
tracking: string,
resource: PerformanceResourceTiming
) => void;
declare global {
var _tracking: string;
var resourceObserverCallback: Handler;
}
export class ClassToBeTested {
private resourceObserver: PerformanceObserver;
constructor() {
const callBack = this.getPerformanceObserverCallback(
_tracking,
resourceObserverCallback,
performance
);
this.resourceObserver = PerformanceObserverFactory.create(callBack);
this.resourceObserver.observe({ entryTypes: ['resource'] });
}
getPerformanceObserverCallback(
tracking: string,
handler: Handler,
performance: Performance
): PerformanceObserverCallback {
return (list) => {
const resourceEntries = list.getEntriesByType(
'resource'
) as PerformanceResourceTiming[];
for (const resource of resourceEntries) {
handler(tracking, resource);
}
performance.clearResourceTimings();
};
}
}
Run Code Online (Sandbox Code Playgroud)
最后,我们有测试本身:
import { ClassToBeTested, Handler } from './ClassToBeTested';
import PerformanceObserverFactory from './PerformanceObserverFactory';
import { mock } from 'jest-mock-extended';
describe('ClassToBeTested.constructor', () => {
beforeEach(() => {
PerformanceObserverFactory.reset();
});
it('Should subscribe to PerformanceObserver with correct params', () => {
const observeMock = jest.fn();
PerformanceObserverFactory.setMockedIsntance({
observe: observeMock,
} as unknown as PerformanceObserver);
const testSubject = new ClassToBeTested();
expect(observeMock).toHaveBeenCalledWith({ entryTypes: ['resource'] });
});
});
describe('ClassToBeTested.getPerformanceObserverCallback', () => {
beforeEach(() => {
PerformanceObserverFactory.reset();
});
it('Should call the resourceObserverCallback for eeach list entry and then call clearResourceTimings once', () => {
const entryListResult: Array<PerformanceResourceTiming> = [
{ name: 'name 1' },
{ name: 'name 2' },
] as Array<PerformanceResourceTiming>;
const resourceObserverCallbackMock = jest.fn();
const _tracking = 'I do not know what this is';
const performanceMock = mock<Performance>();
const entryList = mock<PerformanceObserverEntryList>();
entryList.getEntriesByType.mockReturnValue(entryListResult);
PerformanceObserverFactory.setMockedIsntance({
observe: jest.fn(),
} as unknown as PerformanceObserver);
const testSubject = new ClassToBeTested();
const theCallback = testSubject.getPerformanceObserverCallback(
_tracking,
resourceObserverCallbackMock,
performanceMock
);
//lets call it to test it
theCallback(entryList, mock<PerformanceObserver>());
expect(entryList.getEntriesByType).toHaveBeenCalledTimes(1);
expect(resourceObserverCallbackMock).toHaveBeenCalledTimes(
entryListResult.length
);
expect(performanceMock.clearResourceTimings).toHaveBeenCalled();
// we check that each item in the result list is processed
entryListResult.forEach((item, index) => {
expect(resourceObserverCallbackMock).toHaveBeenNthCalledWith(
index + 1,
_tracking,
item
);
});
});
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
332 次 |
| 最近记录: |