tutorial tipos mitocode inyeccion framework explicacion dependencias dependencia tdd requirejs typescript amd

tdd - tipos - spring framework tutorial 2



Inyección de dependencia en TypeScript (7)

Estoy buscando las posibilidades de hacer TDD con TypeScript. Si escribo mis pruebas en TypeScript, ¿es posible hacer que las declaraciones de importación devuelvan burlas para mi clase bajo prueba? ¿O es el único enfoque viable para escribir las pruebas en javascript puro y tratar con la inyección de AMD yo mismo?


He desarrollado un contenedor IoC llamado InversifyJS con funciones avanzadas de inyección de dependencias, como enlaces contextuales.

Debe seguir 3 pasos básicos para usarlo:

1. Agregue anotaciones

La API de anotación está basada en 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. Declarar enlaces

La API de enlace se basa en 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. Resolver dependencias

La API de resolución se basa en 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 última versión (2.0.0) admite muchos casos de uso:

  • Módulos Kernel
  • Kernel middleware
  • Use clases, cadenas literales o símbolos como identificadores de dependencia
  • Inyección de valores constantes
  • Inyección de constructores de clase
  • Inyección de fábricas
  • Auto fábrica
  • Inyección de proveedores (fábrica asíncrona)
  • Controladores de activación (utilizados para inyectar proxies)
  • Inyecciones múltiples
  • Encuadernaciones etiquetadas
  • Decoradores de etiquetas personalizadas
  • Enlaces nombrados
  • Enlaces contextuales
  • Excepciones amistosas (por ejemplo, dependencias circulares)

Puede obtener más información al respecto en https://github.com/inversify/InversifyJS


Para las personas que usan Angular2 he desarrollado Fluidez de inyección https://www.npmjs.com/package/fluency-injection . La documentación es bastante completa e imita el comportamiento de la DI de Angular2.

Los comentarios son muy apreciados y espero que te ayuden :)


Pruebe este Inyector de Dependencia (Tipo)

Typejector GitHub

Con el nuevo TypeScript 1.5 es posible utilizar la forma de anotación

Por ejemplo

@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();

Para el caso de la pregunta: algunas propiedades deberían realizar pseudo Interfaz (o clase abstracta) como en el siguiente ejemplo.

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();

Nota: La inyección simulada debe definirse después del código fuente, ya que redefine el creador de clase para la interfaz


Puede dar una oportunidad: https://www.npmjs.com/package/easy-injectionjs . Es un paquete de inyección de dependencia de uso genérico.

@EasySingleton crea una instancia única de la dependencia a través de toda la aplicación. Es ideal para un servicio de algún tipo.

@EasyPrototype crea tantas instancias de la dependencia como sea necesario. Es ideal para dependencias cambiables.

@EasyFactory se usa principalmente para herencia:

Puede hacer cualquier cosa con este paquete: Uso simple (procedente del archivo léame):

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

Incluso si desea inyectar módulos de nodo, puede hacer esto:

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)

Por supuesto, el uso del servidor express no es para el registro de la consola. Es solo para probar: D.

Espero que ayude: D


Trabajo en AutoFixtureTS que está inspirado en AutoFixture. AutoFixtureTS hace que sea más fácil para los desarrolladores de TypeScript realizar un desarrollo basado en pruebas mediante la automatización de la configuración de dispositivos de prueba no relevante, lo que permite que el desarrollador de pruebas se centre en los aspectos esenciales de cada caso de prueba.

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

Sigue siendo solo un prototipo de código, pero échale un vistazo :-)

/ ronnie


TypeScript funciona bien con cargadores AMD como requirejs. Si se confgura correctamente, TypeScript generará javascript completamente compatible con AMD.

En una situación de prueba, puede configurar requirejs para inyectar módulos comprobables.


Yo uso infuse.js para Dependency Injection en TypeScript.

Referencia los d.ts

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

Inicialice su inyector al inicio

this.injector = new infuse.Injector();

Dependencias del mapa

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

Inyectar dependencias

export class TodoController { static inject = [''TodoView'', ''TodoModel'']; constructor( todoView:TodoView, todoModel:TodoModel ) { } }

Se basa en cadenas en lugar de estar basado en el tipo (ya que la reflexión aún no es posible en TypeScript). A pesar de eso, funciona muy bien en mis aplicaciones.