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).