Подтвердить что ты не робот

Впрыск зависимости в TypeScript

Я изучаю возможности делать TDD с помощью TypeScript. Если я напишу свои тесты в TypeScript, можно ли заставить операторы импорта возвращать mocks для моего тестируемого класса? Или это единственный возможный подход, чтобы писать тесты в чистом javascript и заниматься инъекцией AMDs?

4b9b3361

Ответ 1

Я использую infuse.js для инъекций зависимостей в TypeScript.

Ссылка на d.ts

/// <reference path="definition/infusejs/infusejs.d.ts"/>

Инициализировать инжектор при запуске

this.injector = new infuse.Injector();  

Зависимости карт

this.injector.mapClass( 'TodoController', TodoController );
this.injector.mapClass( 'TodoView', TodoView );
this.injector.mapClass( 'TodoModel', TodoModel, true );  // 'true' Map as singleton

Зависимости вложения

export class TodoController
{
    static inject = ['TodoView', 'TodoModel'];

    constructor( todoView:TodoView, todoModel:TodoModel )
    {

    }
 }

Это строка, основанная, в отличие от того, что она основана на типе (поскольку отражение еще не возможно в TypeScript). Несмотря на это, он очень хорошо работает в моих приложениях.

Ответ 2

Я разработал контейнер IoC под названием InversifyJS с расширенными функциями впрыска зависимостей, такими как контекстные привязки.

Вам необходимо выполнить 3 основных шага:

1. Добавить аннотации

API аннотации основан на Angular 2.0:

import { injectable, inject } from "inversify";

@injectable()
class Katana implements IKatana {
    public hit() {
        return "cut!";
    }
}

@injectable()
class Shuriken implements IShuriken {
    public throw() {
        return "hit!";
    }
}

@injectable()
class Ninja implements INinja {

    private _katana: IKatana;
    private _shuriken: IShuriken;

    public constructor(
        @inject("IKatana") katana: IKatana,
        @inject("IShuriken") shuriken: IShuriken
    ) {
        this._katana = katana;
        this._shuriken = shuriken;
    }

    public fight() { return this._katana.hit(); };
    public sneak() { return this._shuriken.throw(); };

}

2. Объявлять привязки

API привязки основан на Ninject:

import { Kernel } from "inversify";

import { Ninja } from "./entities/ninja";
import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";

var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);

export default kernel;

3. Разрешить зависимости

API-интерфейс разрешения основан на Ninject:

import kernel = from "./inversify.config";

var ninja = kernel.get<INinja>("INinja");

expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true

Последняя версия (2.0.0) поддерживает множество вариантов использования:

  • Модули ядра
  • промежуточное ПО ядра
  • Использование классов, строковых литералов или символов в качестве идентификаторов зависимостей
  • Инъекция постоянных значений
  • Впрыскивание конструкторов классов
  • Инъекция фабрик
  • Авто factory
  • Инъекция поставщиков (async factory)
  • Обработчики активации (используемые для ввода прокси)
  • Несколько инъекций
  • Отмеченные привязки
  • Декодеры пользовательских тегов
  • Именованные привязки
  • Контекстные привязки
  • Дружественные исключения (например, круговые зависимости)

Подробнее об этом можно узнать на https://github.com/inversify/InversifyJS

Ответ 3

Попробуйте Инъектор зависимостей (Typejector)

GitHub Typejector

С новым TypeScript 1.5 можно использовать способ аннотации

Например

    @injection
    class SingletonClass {
        public cat: string = "Kitty";
        public dog: string = "Hot";

        public say() {
            alert(`${this.cat}-Cat and ${this.dog}-Dog`);
        }
    }
    @injection
    class SimpleClass {
        public say(something: string) {
            alert(`You said ${something}?`);
        }
    }

    @resolve
    class NeedInjectionsClass {
        @inject(SingletonClass)
        public helper: SingletonClass;
        @inject(SimpleClass)
        public simpleHelper: SimpleClass;

        constructor() {
            this.helper.say();
            this.simpleHelper.say("wow");
        }
    }
    class ChildClass extends NeedInjectionsClass {

    }

    var needInjection = new ChildClass();

Для вопроса: некоторое свойство должно реализовать псевдо-интерфейс (или абстрактный класс), как в следующем примере.

    class InterfaceClass {
        public cat: string;
        public dog: string;

        public say() {

        }
    }

    @injection(true, InterfaceClass)
    class SingletonClass extends InterfaceClass {
        public cat: string = "Kitty";
        public dog: string = "Hot";

        public say() {
            alert(`${this.cat}-Cat and ${this.dog}-Dog`);
        }
    }

    @injection(true, InterfaceClass)
    class MockInterfaceClass extends InterfaceClass {
        public cat: string = "Kitty";
        public dog: string = "Hot";

        public say() {
            alert(`Mock-${this.cat}-Cat and Mock-${this.dog}-Dog`);
        }
    }

    @injection
    class SimpleClass {
        public say(something: string) {
            alert(`You said ${something}?`);
        }
    }

    @resolve
    class NeedInjectionsClass {
        @inject(InterfaceClass)
        public helper: InterfaceClass;
        @inject(SimpleClass)
        public simpleHelper: SimpleClass;

        constructor() {
            this.helper.say();
            this.simpleHelper.say("wow");
        }
    }

    class ChildClass extends NeedInjectionsClass {

    }

    var needInjection = new ChildClass();

Примечание: Вредоносная инъекция должна определяться после исходного кода, поскольку маска переопределяет класс-создателя для интерфейса

Ответ 4

Для людей, которые используют Angular2, я разработал Fluency Injection https://www.npmjs.com/package/fluency-injection. Документация достаточно полная и имитирует поведение Angular2 DI.

Обратная связь очень ценится, и я надеюсь, что это вам поможет:)

Ответ 5

TypeScript хорошо работает с загрузчиками AMD, такими как requirejs. Если он корректно завершен, TypeScript будет выводить полностью совместимый с AMD javascript.

В тестовой ситуации вы можете настроить requirejs для ввода тестируемых модулей.

Ответ 6

Я работаю над AutoFixtureTS, вдохновленным AutoFixture. AutoFixtureTS упрощает разработку TypeScript разработчиками Test-Driven Development, автоматизируя не относящуюся к делу установку Test Fixture, позволяя разработчику теста сосредоточиться на необходимости каждого тестового примера.

http://ronniehegelund.github.io/AutoFixtureTS/

Его еще только прототип кода, но проверьте его: -)

/Ronnie