0

Как создать заглушку для интерфейса / определения типа в TypeScript?

9

Я работаю с Typescript в проекте на AngularJS 1.X и использую различные JavaScript-библиотеки для разных целей. Для юнит-тестирования моего исходного кода я хотел бы замокать некоторые зависимости, используя типы (интерфейсы). Я не хочу использовать тип ANY и не хочу писать пустое тело для каждого метода интерфейса.

Я ищу способ сделать что-то вроде следующего:

let dependency = stub(IDependency);
stub(dependency.b(), () => { console.log("Hello World") });
dependency.a(); // --> Компилируется, ничего не делает, без исключений
dependency.b(); // --> Компилируется, печатает "Hello World", без исключений

У меня сейчас проблема в том, что я либо использую any и реализую все методы, которые вызываются в моем тесте, либо реализую интерфейс и пишу полную его реализацию. Это слишком много лишнего кода 😦

Как я могу сгенерировать объект, который имеет пустую реализацию для каждого метода и при этом типизирован? Я использую Sinon для мокирования, но готов рассмотреть и другие библиотеки.

P.S. Я знаю, что Typescript удаляет интерфейсы, но мне все равно хотелось бы решить эту задачу.

2 ответ(ов)

0

Краткий ответ заключается в том, что это невозможно в TypeScript, так как язык не предоставляет возможностей для "рефлексии" на этапе компиляции или выполнения. Мок-библиотекам не под силу итерировать члены интерфейса.

Смотрите обсуждение: https://github.com/Microsoft/TypeScript/issues/1549

Это, к сожалению, создает трудности для разработчиков, использующих TDD, поскольку мокирование зависимости является центральной частью рабочего процесса разработки.

Тем не менее, существует несколько техник для быстрой заглушки методов, как описано в других ответах. Эти варианты могут подойти, если немного адаптировать подход.

Правка: Абстрактное синтаксическое дерево TypeScript (AST) является примером "интроспекции" на этапе компиляции — и его можно было бы использовать для генерации моков. Однако я не знаю, создало ли кто-то практическую библиотеку для этой цели.

0

В библиотеке ts-mockito появилась возможность мокирования интерфейсов с версии 2.4.0. Для этого вместо передачи типа в функцию mock, установите тип как обобщение (generic type). Это требует реализации Proxy. Вот пример:

let mockedFoo: Foo = mock<FooInterface>(); // вместо mock(FooInterface)
const foo: SampleGeneric<FooInterface> = instance(mockedFoo);

Для получения дополнительной информации и скачивания новой версии можно ознакомиться с официальной страницей пакета на npm или записью о релизе на GitHub.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь