unit test run angular typescript unit-testing jasmine angular-test

run - unit test angular 5



Prueba unitaria Angular2 con @Input() (4)

Debe establecer el valor del product en la instancia del componente después de que se haya cargado dentro de su prueba.

Como muestra, aquí hay un componente simple dentro de una entrada que puede usar como base para su caso de uso:

@Component({ selector: ''dropdown'', directives: [NgClass], template: ` <div [ngClass]="{open: open}"> </div> `, }) export class DropdownComponent { @Input(''open'') open: boolean = false; ngOnChanges() { console.log(this.open); } }

Y la prueba correspondiente:

it(''should open'', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => { return tcb.createAsync(DropdownComponent) .then(fixture => { let el = fixture.nativeElement; let comp: DropdownComponent = fixture.componentInstance; expect(el.className).toEqual(''''); // Update the input comp.open = true; // <----------- // Apply fixture.detectChanges(); // <----------- var div = fixture.nativeElement.querySelector(''div''); // Test elements that depend on the input expect(div.className).toEqual(''open''); }); }));

Vea este plunkr como muestra: https://plnkr.co/edit/YAVD4s?p=preview .

Tengo un componente que usa la anotación @Input() en una variable de instancia y estoy tratando de escribir mi prueba unitaria para el método openProductPage() , pero estoy un poco perdido en cómo configuro mi prueba unitaria. Podría hacer pública esa variable de instancia, pero no creo que deba recurrir a eso.

¿Cómo configuro mi prueba de Jasmine para que se inyecte un producto openProductPage() ) y pueda probar el método openProductPage() ?

Mi componente:

import {Component, Input} from "angular2/core"; import {Router} from "angular2/router"; import {Product} from "../models/Product"; @Component({ selector: "product-thumbnail", templateUrl: "app/components/product-thumbnail/product-thumbnail.html" }) export class ProductThumbnail { @Input() private product: Product; constructor(private router: Router) { } public openProductPage() { let id: string = this.product.id; this.router.navigate([“ProductPage”, {id: id}]); } }


Esto es de la documentación oficial https://angular.io/docs/ts/latest/guide/testing.html#!#component-fixture . Por lo tanto, puede crear un nuevo objeto de entrada expectHero y pasarlo al componente comp.hero =pectedHero

También asegúrese de llamar a fixture.detectChanges(); por último, de lo contrario, la propiedad no estará vinculada al componente.

Ejemplo de trabajo

// async beforeEach beforeEach( async(() => { TestBed.configureTestingModule({ declarations: [ DashboardHeroComponent ], }) .compileComponents(); // compile template and css })); // synchronous beforeEach beforeEach(() => { fixture = TestBed.createComponent(DashboardHeroComponent); comp = fixture.componentInstance; heroEl = fixture.debugElement.query(By.css(''.hero'')); // find hero element // pretend that it was wired to something that supplied a hero expectedHero = new Hero(42, ''Test Name''); comp.hero = expectedHero; fixture.detectChanges(); // trigger initial data binding });


Si usa TestBed.configureTestingModule para compilar su componente de prueba, aquí hay otro enfoque. Básicamente es lo mismo que la respuesta aceptada, pero puede ser más similar a cómo angular-cli genera las especificaciones. FWIW

import { Component, CUSTOM_ELEMENTS_SCHEMA } from ''@angular/core''; import { async, ComponentFixture, TestBed } from ''@angular/core/testing''; import { DebugElement } from ''@angular/core''; describe(''ProductThumbnail'', () => { let component: ProductThumbnail; let fixture: ComponentFixture<TestComponentWrapper>; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ TestComponentWrapper, ProductThumbnail ], schemas: [CUSTOM_ELEMENTS_SCHEMA] }) .compileComponents(); fixture = TestBed.createComponent(TestComponentWrapper); component = fixture.debugElement.children[0].componentInstance; fixture.detectChanges(); }); it(''should create'', () => { expect(component).toBeTruthy(); }); }); @Component({ selector: ''test-component-wrapper'', template: ''<product-thumbnail [product]="product"></product-thumbnail>'' }) class TestComponentWrapper { product = new Product() }


Usualmente hago algo como:

describe(''ProductThumbnail'', ()=> { it(''should work'', injectAsync([ TestComponentBuilder ], (tcb: TestComponentBuilder) => { return tcb.createAsync(TestCmpWrapper).then(rootCmp => { let cmpInstance: ProductThumbnail = <ProductThumbnail>rootCmp.debugElement.children[ 0 ].componentInstance; expect(cmpInstance.openProductPage()).toBe(/* whatever */) }); })); } @Component({ selector : ''test-cmp'', template : ''<product-thumbnail [product]="mockProduct"></product-thumbnail>'', directives: [ ProductThumbnail ] }) class TestCmpWrapper { mockProduct = new Product(); //mock your input }

Tenga en cuenta que el product y cualquier otro campo en la clase ProductThumbnail pueden ser privados con este enfoque (que es la razón principal por la que lo prefiero sobre el enfoque de Thierry, a pesar de que es un poco más detallado).