Как интерфейс Flow.js можно смоделировать с помощью Jest ? К моему удивлению, я нигде не нашел, чтобы эта проблема была решена.
Я довольно новичок в обоих случаях, но единственный (непроверенный) вариант, который я вижу, - это создать класс, который наследует от интерфейса, а затем смоделировать реализующий класс. Это кажется довольно обременительным, и я не верю, что мог бы поместить реализующие классы (которые на самом деле должны были бы быть смоделированы) в папки __mocks__
, ожидаемые Jest, и все еще получить ожидаемое поведение.
Есть предложения? Есть ли более подходящий инструмент для насмешек?
Обновление
Почему я хочу создать макет для интерфейса? Этот код предназначен для четкого разделения уровня домена и уровня реализации, при этом классы домена используют интерфейсы Flow для всех внедренных зависимостей. Я хочу проверить эти классы домена. Использование инструмента для проверки подлинности может в идеале позволить мне более легко и выразительно изменить поведение проверенных служб и подтвердить, что проверяемый класс домена выполняет соответствующие вызовы для этих проверенных служб.
Вот упрощенный пример класса, который я буду тестировать в этом сценарии. UpdateResources
будет тестируемым классом, в то время как ResourceServer
и ResourceRepository
являются интерфейсами для служб, над которыми я хотел бы посмеяться и «шпионить» за:
// @flow
import type { ResourceServer } from '../ResourceServer';
import type { ResourceRepository } from '../ResourceRepository';
/**
* Use case for updating resources
*/
export default class UpdateResources {
resourceServer: ResourceServer;
resourceRepository: ResourceRepository;
constructor(resourceServer: ResourceServer, resourceRepository: ResourceRepository) {
this.resourceServer = resourceServer;
this.resourceRepository = resourceRepository;
}
async execute(): Promise<boolean> {
const updatesAvailable = await this.resourceServer.checkForUpdates();
if (updatesAvailable) {
const resources = await this.resourceServer.getResources();
await this.resourceRepository.saveAll(resources);
}
return updatesAvailable;
}
}
Решение
Подход, к которому я пришел, который, кажется, работает достаточно хорошо для моих целей, состоит в том, чтобы создать фиктивную реализацию интерфейса в каталоге __mocks__
, которая предоставляет объекты jest.fn
для всех реализованных методов. Затем я создаю эти ложные реализации с new
и пропускаю любое использование jest.mock()
.
__ издевается __ / MockResourceServer.js
import type { ResourceServer } from '../ResourceServer';
export default class MockResourceServer implements ResourceServer {
getResources = jest.fn(() => Promise.resolve({}));
checkForUpodates = jest.fn(() => Promise.resolve(true));
}
__ издевается __ / MockResourceRepository.js
import type { ResourceRepository } from '../ResourceRepository';
export default class MockResourceRepository implements ResourceRepository {
saveAll = jest.fn(() => Promise.resolve());
}
__ __ тесты / UpdateResources.test.js
import UpdateResources from '../UpdateResources';
import MockResourceRepository from '../../__mocks__/MockResourceRepository';
import MockResourceServer from '../../__mocks__/MockResourceServer';
describe('UpdateResources', () => {
describe('execute()', () => {
const mockResourceServer = new MockResourceServer();
const mockResourceRepository = new MockResourceRepository();
beforeEach(() => {
jest.clearAllMocks();
});
it('should check the ResourceServer for updates', async () => {
const updateResources = new UpdateResources(mockResourceServer, mockResourceRepository);
await updateResources.execute();
expect(mockResourceServer.checkForUpdates).toHaveBeenCalledTimes(1);
});
it('should save to ResourceRepository if updates are available', async () => {
mockResourceServer.load.mockResolvedValue(true);
const updateResources = new UpdateResources(mockResourceServer, mockResourceRepository);
await updateResources.execute();
expect(mockResourceRepository.saveAll).toHaveBeenCalledTimes(1);
});
it('should NOT save to ResourceRepository if NO updates are available', async () => {
mockResourceServer.load.mockResolvedValue(false);
const updateResources = new UpdateResources(mockResourceServer, mockResourceRepository);
await updateResources.execute();
expect(mockResourceRepository.saveAll).not.toHaveBeenCalled();
});
});
});
Если кто-нибудь может предложить какие-либо улучшения, я открыт!