Je regarde les possibilités de faire TDD avec TypeScript . Si j'écris mes tests en TypeScript, est-il possible de faire en sorte que les instructions import renvoient des alarmes pour ma classe sous test? écrire les tests en javascript pur et s’injecter moi-même des AMD?
J'utilise infuse.js pour Dependency Injection dans TypeScript.
/// <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 )
{
}
}
Il s'agit d'une chaîne basée sur le type (car la réflexion n'est pas encore possible dans TypeScript). Malgré cela, cela fonctionne très bien dans mes applications.
J'ai développé un conteneur IoC appelé InversifyJS avec des fonctionnalités avancées d'injection de dépendance, telles que les liaisons contextuelles.
Vous devez suivre 3 étapes de base pour l'utiliser:
L'API d'annotation est basée sur 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(); };
}
L'API de liaison est basée sur 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;
L'API de résolution est basée sur Ninject:
import kernel = from "./inversify.config";
var ninja = kernel.get<INinja>("INinja");
expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true
La dernière version (2.0.0) prend en charge de nombreux cas d'utilisation:
Vous pouvez en apprendre plus à ce sujet sur https://github.com/inversify/InversifyJS
Essayez ceci Dependency Injector (Typejector)
GitHub Typejector
Avec le nouveau TypeScript 1.5, il est possible d’utiliser des annotations
Par exemple
@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();
Pour le cas question: Une propriété devrait réaliser une pseudo interface (ou classe abstraite) comme dans l'exemple suivant.
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();
Note: _ L'injection simulée devrait définir après le code source car elle redéfinit le créateur de classe pour l'interface
Pour les personnes utilisant Angular2, j'ai développé Fluency Injection https://www.npmjs.com/package/fluency-injection . La documentation est assez complète et imite le comportement du DI de Angular2.
Les commentaires sont très appréciés et j'espère que cela vous aidera :)
Vous pouvez essayer ceci: https://www.npmjs.com/package/easy-injectionjs . C'est un package d'injection de dépendance d'usage générique.
@EasySingleton crée une instance unique de la dépendance dans toute l'application. C'est idéal pour un service quelconque.
@EasyPrototype crée autant d'instances de la dépendance que nécessaire. C'est idéal pour les dépendances changeantes.
@EasyFactory est principalement utilisé pour l'héritage:
Vous pouvez faire n'importe quoi en utilisant ce paquet: Utilisation simple
import { Easy, EasyFactory, EasyPrototype, EasySingleton } from 'easy-injectionjs';
@EasyFactory()
abstract class Person {
abstract getName();
abstract setName(v: string);
}
// @EasyObservable()
@EasySingleton()
class Somebody extends Person{
// @Easy()
constructor (private name: string) {
super()
this.name = 'Sal';
}
public getName() {
return this.name;
}
public setName(v: string) {
this.name = v;
}
}
@EasyPrototype()
class Nobody extends Person{
@Easy()
somebody: Person;
constructor () {
super()
}
public getName() {
return this.somebody.getName();
}
public setName(v: string) {
this.somebody.setName(v);
}
}
@EasyPrototype()
class Data {
@Easy()
somebody: Person;
name: string;
change(v: string) {
this.somebody.setName(v);
}
getName(): string {
return this.somebody.getName();
}
}
let n = new Nobody();
console.log(n.getName()) // Prints Sal
n.setName('awesome');
console.log(n.getName()) // Prints awesome
let d = new Data()
console.log(d.getName()) // Prints awesome
d.change('Gelba')
console.log(n.getName()) // Prints Gelba
d.change('kaa')
console.log(n.getName()) // Prints Kaa
Même si vous souhaitez injecter des modules de nœud, vous pouvez le faire:
import * as IExpress from 'express';
import { Easy, EasySingleton } from 'easy-injectionjs';
@EasySingleton()
class Express extends IExpress {}
@EasySingleton()
export class App {
@Easy()
private _express: Express;
}
let app = new App();
console.log(app)
Bien entendu, l'utilisation du serveur express ne sert pas à la journalisation de la console. C'est juste pour tester: D.
J'espère que ça aide: D
TypeScript fonctionne bien avec les chargeurs AMD tels que requirejs. S'il est configuré correctement, TypeScript générera un javascript conforme à AMD.
Dans une situation de test, vous pouvez configurer requirejs pour injecter des modules testables.