
Co-authored-by: Michael Prentice <splaktar@gmail.com> Co-authored-by: Gustavo Rodríguez <47954465+gustavguez@users.noreply.github.com> Fix #231
21 KiB
APIs de Utilidades de Testing
Esta página describe las funciones de testing más útiles de Angular
Las funciones de testing de Angular incluyen la TestBed
, el ComponentFixture
y varias funciones que controlan el medio de pruebas
Las clases TestBed y ComponentFixture se tratan aparte.
Este es un resumen de todas las funciones autocontenidas, en orden de posible utilidad:
<td>
Ejecuta el conjunto de una función test (`it`) o setup (`beforeEach`) desde una _zona de pruebas asíncrona_
Consulta [esta discusión](guide/testing-components-scenarios#waitForAsync).
</td>
<td>
Ejecuta el conjunto de un test (`it`) desde una _zona falsa de pruebas asíncrona_ especial, permitiendo un estilo de código de flujo de control lineal.
Consulta [esta discusión](guide/testing-components-scenarios#fake-async).
</td>
<td>
Simula el paso del tiempo y completar actividades asíncronas pendientes haciendo flush tanto en el _cronómetro_ como en la _cola de micro-tareas_ desde la _zona falsa de pruebas asíncronas_
<div class="alert is-helpful">
Algún lector curioso y dedicado quizá disfrute de la lectura de esta extensa publicación en un blog:
["_Tasks, microtasks, queues and schedules_"](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/).
</div>
Acepta un argumento adicionar que adelanta el reloj virtual según el número especificado de milisegundos, despejando las actividades asíncronas planeadas para ese bloque de tiempo
Consulta [esta discusión](guide/testing-components-scenarios#tick).
</td>
<td>
Inyecta uno o más servicios desde la `TestBed` inyectora actual hacia una función de test.
No puede inyectar un servicio proveído por el componente en sí.
Consulta [debugElement.injector](guide/testing-components-scenarios#get-injected-services).
</td>
<td>
Cuando un `fakeAsync()` test finaliza con tareas cronometradas pendientes (llamadas a `setTimeOut` y `setInterval` en cola), el test finaliza con un mensaje de error vacío.
En general, un test debería finalizar sin tareas en cola. Cuando esperamos tareas cronometradas pendientes, llamamos a `discardPeriodicTasks` para hacer flush a la cola de tareas y evitar el error.
</td>
<td>
Cuando un test `fakeAsync()` finaliza con micro-tareas pendientes como promesas sin resolver, el test finaliza con un mensaje de error vacío
En general, un test debería esperar a que acaben las micro-tareas. Cuando quedan micro-tareas pendientes en cola, llamamos a `flushMicrotasks` para hacer flush a la cola de micro-tareas y evitar el error.
</td>
<td>
Un token del proveedor que inicia la [detección automática de cambios](guide/testing-components-scenarios#automatic-change-detection).
</td>
<td>
Toma la instancia actual de la `TestBed`.
Normalmente es innecesaria porque los métodos de clase estáticos de `TestBed` suelen ser suficientes.
La instancia de `TestBed` muestra algunos miembros menos comunes que no están disponibles como métodos estáticos
</td>
Función | Descripción |
---|---|
async
|
|
fakeAsync
|
|
tick
|
|
inject
|
|
discardPeriodicTasks
|
|
flushMicrotasks
|
|
ComponentFixtureAutoDetect
|
|
getTestBed
|
{@a resumen-clase-testbed}
Resumen de la clase TestBed
La clase TestBed
es una de las utilidades de testing principales de Angular. Su API es bastante grande y puede ser sobrecogedora hasta que la has explorado, ve poco a poco. Puedes leer la parte inicial de esta guía primero para familiarizarte con lo básico antes de intentar aprender toda la API.
La definición del módulo que pasamos a configureTestingModule
es un subconjunto de las propiedades metadata de @NgModule
.
{@a metadata-override-object}
Cada método de sobreescribir toma un MetadataOverride<T>
donde T
es el tipo de metadato apropiado para el método, es decir, el parámetro de un @NgModule
,
@Component
, @Directive
, o @Pipe
.
{@a testbed-métodos} {@a testbed-api-summary}
La API TestBed
consiste de métodos de clase estáticos que o actualizan o referencian una instancia global de TestBed
.
Internamente, todos los métodos estáticos cubren los métodos de la instancia TestBed
actual, lo cual también es devuelto por la función getTestBed()
.
Llama a los métodos TestBed
desde un beforeEach()
para asegurarte de tener un inicio en blanco antes de cada test individual.
Aquí están los métodos estáticos más importantes, en orden de posible utilidad.
<td>
Los shims de prueba (`karma-test-shim, `browser-test-shim`) establecen el [medio de pruebas inicial](guide/testing)y un módulo de pruebas por defecto.
El módulo de pruebas por defecto es configurado con declarativas básicas y algunos servicios sustitutos de Angular que cualquier tester necesitaría.
Llama a `configureTestingModule` para refinar la configuración del módulo de pruebas para un conjunto particular de tests, añadiendo o quitando importes, declaraciones (de componentes, directivas, pipes...) y proveedores.
</td>
<td>
Compila el módulo de testing de forma asíncrona después de que hayas finalizado configurándolo.
Debes llamar este método si cualquiera de los componentes de módulo de testing tiene una `templateUrl` o `styleUrls`, porque traer templates de componentes y archivos de estilo es obligatoriamente asíncrono.
Consulta [aquí](guide/testing-components-scenarios#compile-components).
Después de llamar a `compileComponents`, la configuración de `TestBed` se congela durante la especificación actual.
</td>
<td>
Crea una instancia de un componente de tipo `T` basado en la configuración de la `TestBed` actual.
Despuest de llamar a `compileComponent`, la configuración de `TestBed` se congela durante la especificación actual.
</td>
<td>
Reemplaza metadatos para la clase componente dada, la cual puede estar anidada dentro de un módulo interno.
</td>
<td>
Reemplaza metadatos para la clase directiva dada, la cual puede estar anidada dentro de un módulo interno.
</td>
<td>
Trae un servicio del inyector `TestBed` actual.
La función `inject` normalmente es adecuada para esto, pero lanza un error si no puede proveer el servicio
¿Qué pasa si el servicio es opcional?
El método `TestBed.inject()` toma un segundo parámetro opcional, el objeto para devolver si Angular no encuentra el proveedor (nulo, en este ejemplo):
<code-example path="testing/src/app/demo/demo.testbed.spec.ts" region="testbed-get-w-null" header="app/demo/demo.testbed.spec.ts"></code-example>
Después de llamar a `TestBed.inject`, la configuración de `TestBed` se congela durante la especificación actual.
</td>
Métodos | Descripción |
---|---|
configureTestingModule
|
|
compileComponents
|
|
createComponent
|
|
overrideModule
|
|
overrideComponent
|
|
overrideDirective
|
|
overridePipe
|
|
{@a testbed-inject}
inject
|
|
{@a testbed-initTestEnvironment}
initTestEnvironment
|
|
resetTestEnvironment
|
|
Algunos de los métodos de instancia de TestBed
no son cubiertos por los métodos estáticos de clase de TestBed
. Estos no suelen utilizarse.
{@a component-fixture-api-summary}
El ComponentFixture
TestBed.createComponent<T>
crea una instancia de un componente T
y devuelve un ComponentFixture
fuertemente tipificado para ese componente
Las propiedades y métodos de ComponentFixture
permiten acceso al componente, su representación DOM y algunos aspectos del medio Angular.
{@a componentes-fixture-propiedades}
Propiedades de ComponentFixture
Aquí están las propiedades más importantes para testers, en orden de posible utilidad.
<td>
La instancia de la clase componente creada por `TestBed.createComponent`.
</td>
<td>
El `DebugElement` asociado con el elemento raíz del componente.
El `DebugElement` da información sobre el componente y su elemento DOM durante el test y debug.
Es una propiedad crítica para los testers. Los miembros más interesantes están cubiertos [aquí](#debug-element-details).
</td>
<td>
El elemento DOM nativo en la raíz del componente.
</td>
<td>
El `ChangeDetectorRef` para el componente.
El `ChangeDetectorRef` es más valioso cuando testeamos un componente que tiene el método`ChangeDetectionStrategy.OnPush` o cuando la detección de cambios del componente está bajo tu control programático.
</td>
Propiedades | Descripción |
---|---|
componentInstance
|
|
debugElement
|
|
nativeElement
|
|
changeDetectorRef
|
{@a componente-fixture-métodos}
Métodos de ComponentFixture
Los métodos fixture hacen que Angular ejecute mejor ciertas tareas en el árbol de componentes. Llama a estos métodos para iniciar el comportamiento de Angular en respuesta a una acción de usuario simulada.
Aquí están los métodos más útiles para los testers.
<td>
Inicia un ciclo de detección de cambios para el componente.
Llámalo para inicializar el componente (que llama a `ngOnInit`) y después de tu código de pruebas, cambia los valores de propiedad asociados a los datos de los componentes.
Angular no puede ver que has cambiado `personComponent.name` y no actualizará el `name` hasta que llames a `detectChanges`.
Ejecuta `checkNoChanges` después para confirmar que no hay actualizaciones circulares, a no se que se llame así: `detectChanges(false)`
</td>
<td>
Poner esto a `true` cuando quieras que el fixture detecte los cambios automáticamente.
Set this to `true` when you want the fixture to detect changes automatically.
Cuando autodetect es `true`, el fixture de pruebas llama a `detectChanges` inmediatamente después de crear el componente. Después comprueba los eventos de zona pertinentes y llama a `detectChanges` de forma acorde.
Cuando tu código de pruebas modifique los valores de propiedad de un componente de forma directa, probablemente tengas que llamar a `fixture.detectChanges` para iniciar las actualizaciones de unificación de datos.
El valor por defecto es `false`. Los testers que prefieren tener un control mayor sobre el comportamiento de pruebas suelen dejarlo en `false`.
</td>
<td>
Corre el programa para detectar cambios y asegurarse de que no hay cambios pendientes.
Lanza una excepción si los hay.
</td>
<td>
Si el fixture es actualmente estable, devuelve `true`.
Si hay tareas asíncronas no completadas, devuelve `false`.
</td>
<td>
Devuelve una promesa que resuelve cuando el fixture es estable.
Para volver al testing después de completar actividad asíncrona o detección de cambios asíncronos, añade esta promesa.
Consulta [aquí](guide/testing-components-scenarios#when-stable).
</td>
<td>
Inicia la destrucción del componente
</td>
Métodos | Descripción |
---|---|
detectChanges
|
|
autoDetectChanges
|
|
checkNoChanges
|
|
isStable
|
|
whenStable
|
|
destroy
|
{@a debug-elementos-detalles}
DebugElement
El DebugElement
proporciona información crucial para la representación DOM de los componentes.
Desde el DebugElement
del componente test raíz, devuelto por fixture.debugElement
, puedes llegar a todo elemento y subárbol de componentes del fixture
Aquí están los miembros DebugElement
más útiles para los testers, en orden de posible utilidad:
<td>
El elemento DOM correspondiente en el navegador (nulo para WebWorkers).
</td>
<td>
Llamar a `query(predicate: Predicate<DebugElement>)` devuelbe el primer `DebugElement` que coincida con el [predicado](#query-predicate) a cualquier profundidad en el subárbol
</td>
<td>
Llamar a `queryAll(predicate: Predicate<DebugElement>)` devuelve todos los `DebugElements` que coincidan con el [predicado](#query-predicate) a cualquier profundidad en el subárbol
</td>
<td>
El inyector de dependecia del host. Por ejemplo, el inyector de la instancia del componente del elemento
</td>
<td>
La instancia del componente del propio elemento, si tiene.
</td>
<td>
Un objeto que provee contexto del padre para este elemento.
En muchas ocasiones una instancia del componente ancestro gobierna este elemento.
Cuando un elemento se repite en `*ngFor`, el contexto es un `NgForRow` cuya propiedad `$implicit` es el valor de la instancia de la fila. Por ejemplo, el `hero` en *ngFor="let hero of heroes"`.
</td>
<td>
Los hijos `DebugElement` inmediatos. Recorre el árbol descendiendo a través de los hijos.
<div class="alert is-helpful">
`DebugElement` también tiene `childNodes`, una lista de objetos `DebugNode`.
`DebugElement` deriva de los objetos `DebugNode` y suele haber más nodos que elementos. Los tester normalmente ignoran los nodos planos.
</div>
</td>
<td>
El tag name del elemento, si es que es un elemento.
</td>
<td>
Los callbacks insertados al `@Output` del componente, sus propiedades y/o las propiedades de evento del elemento.
</td>
<td>
Los token de búsqueda del inyector de este componente.
Include el componente en sí mismo además de los tokens que el componente lista en la parte "proveedores" de sus metadatos.
</td>
<td>
Dónde encontrar este elemento en el componente template fuente.
</td>
<td>
Diccionario de objetos asociados a variables locales template (e.g. `#foo`), acuñado por el nombre de la variable local
</td>
Miembro | Descripción |
---|---|
nativeElement
|
|
query
|
|
queryAll
|
|
injector
|
|
componentInstance
|
|
context
|
|
children
|
|
parent
|
|
name
|
|
triggerEventHandler
|
|
listeners
|
|
providerTokens
|
|
source
|
|
references
|
{@a query-predicate}
Los métodos DebugElement.query(predicate)
yDebugElement.queryAll(predicate)
toman un predicado que filtra el subárbol del elemento fuente para igualar a DebugElement
.
El predicado es cualquier método que tome el DebugElement
y devuelva un valor verdadero.
El siguiente ejemplo encuentra todos los DebugElement
con una referencia a una variable local template llamada "content":
La clase Angular By
tiene tres métodos estáticos para predicados comunes:
By.all
- devuelve todos los elementosBy.css(selector)
- devuelve los elementos con selectores CSS coincidentesBy.directive(directive)
- devuelve elementos que Angular ha unido a una instancia de la clase directiva.