expect
Los siguientes tipos se utilizan en las firmas de tipo que se muestran a continuación:
type Awaitable<T> = T | PromiseLike<T>;
expect
se utiliza para crear aserciones. En este contexto, las aserciones son funciones que se invocan para verificar una afirmación. Vitest proporciona aserciones de chai
de forma predeterminada y también aserciones compatibles con Jest
construidas sobre chai
.
Por ejemplo, este código afirma que el valor de input
es igual a 2
. Si no lo es, la aserción lanzará un error y la prueba fallará.
import { expect } from 'vitest';
const input = Math.sqrt(4);
expect(input).to.equal(2); // API de chai
expect(input).toBe(2); // API de jest
Técnicamente, este ejemplo no usa la función test
, por lo que en la consola verá un error de Node.js en lugar de la salida de Vitest. Para obtener más información sobre test
, consulte Referencia de la API de prueba.
Además, expect
se puede usar estáticamente para acceder a las funciones de coincidencia (matchers), que se describen más adelante, y más.
WARNING
expect
no tiene efecto en las pruebas de tipos, si la expresión no genera un error de tipo. Si desea utilizar Vitest como verificador de tipos, utilice expectTypeOf
o assertType
.
soft
- Tipo:
ExpectStatic & (actual: any) => Assertions
expect.soft
funciona de manera similar a expect
, pero en lugar de detener la ejecución de la prueba tras un fallo en la aserción, continúa ejecutándose y marca el fallo como un fallo de prueba. Todos los errores encontrados durante la prueba se mostrarán al finalizar la prueba.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // Marca la prueba como fallida pero continúa
expect.soft(1 + 2).toBe(4); // Marca la prueba como fallida pero continúa
});
// Al final de la prueba, se mostrarán los errores anteriores.
También se puede utilizar con expect
. Si la aserción expect
falla, la prueba terminará y se mostrarán todos los errores.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // Marca la prueba como fallida pero continúa
expect(1 + 2).toBe(3); // Falla y termina la prueba, se mostrarán todos los errores anteriores
expect.soft(1 + 2).toBe(4); // No se llegará a ejecutar
});
WARNING
expect.soft
solo se puede utilizar dentro de la función test
.
not
El uso de not
negará la aserción. Por ejemplo, este código afirma que el valor de input
no es igual a 2
. Si lo es, la aserción lanzará un error y la prueba fallará.
import { expect, test } from 'vitest';
const input = Math.sqrt(16);
expect(input).not.to.equal(2); // API de chai
expect(input).not.toBe(2); // API de jest
toBe
Tipo:
(value: any) => Awaitable<void>
toBe
se puede utilizar para afirmar si los tipos primitivos son iguales o si los objetos comparten la misma referencia. Es equivalente aexpect(Object.is(3, 3)).toBe(true)
. Si los objetos no son los mismos, pero desea comprobar si sus estructuras son idénticas, puede utilizartoEqual
.Por ejemplo, el siguiente código comprueba si el comerciante tiene 13 manzanas.
tsimport { expect, test } from 'vitest'; const stock = { type: 'apples', count: 13, }; test('stock has 13 apples', () => { expect(stock.type).toBe('apples'); expect(stock.count).toBe(13); }); test('stocks are the same', () => { const refStock = stock; // misma referencia expect(stock).toBe(refStock); });
Intente no utilizar
toBe
con números de punto flotante. Dado que JavaScript los redondea,0.1 + 0.2
no es estrictamente0.3
. Para afirmar de forma fiable los números de punto flotante, utilice la asercióntoBeCloseTo
.
toBeCloseTo
Tipo:
(value: number, numDigits?: number) => Awaitable<void>
Utilice
toBeCloseTo
para comparar números de punto flotante. El argumento opcionalnumDigits
limita el número de decimales que se deben comprobar. Por ejemplo:tsimport { expect, test } from 'vitest'; test.fails('decimals are not equal in javascript', () => { expect(0.2 + 0.1).toBe(0.3); // 0.2 + 0.1 es 0.30000000000000004 }); test('decimals are rounded to 5 after the point', () => { // 0.2 + 0.1 es 0.30000 | "000000000004" eliminado expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // no se elimina nada de 0.30000000000000004 expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50); });
toBeDefined
Tipo:
() => Awaitable<void>
toBeDefined
afirma que el valor no es igual aundefined
. Un caso de uso común es comprobar si una función devolvió un valor.tsimport { expect, test } from 'vitest'; function getApples() { return 3; } test('function returned something', () => { expect(getApples()).toBeDefined(); });
toBeUndefined
Tipo:
() => Awaitable<void>
Opuesto a
toBeDefined
,toBeUndefined
afirma que el valor es igual aundefined
. Un caso de uso común es comprobar si una función no devolvió ningún valor.tsimport { expect, test } from 'vitest'; function getApplesFromStock(stock) { if (stock === 'Bill') return 13; } test("mary doesn't have a stock", () => { expect(getApplesFromStock('Mary')).toBeUndefined(); });
toBeTruthy
Tipo:
() => Awaitable<void>
toBeTruthy
afirma que el valor es verdadero cuando se convierte a booleano. Útil si no importa el valor en sí, sino solo si se evalúa comotrue
en un contexto booleano.Por ejemplo, si tiene este código, no le importa el valor de retorno de
stocks.getInfo
: puede ser un objeto complejo, una cadena o cualquier otra cosa. El código seguirá funcionando.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (stocks.getInfo('Bill')) stocks.sell('apples', 'Bill');
Por lo tanto, si desea probar que
stocks.getInfo
será verdadero, podría escribir:tsimport { expect, test } from 'vitest'; import { Stocks } from './stocks.js'; const stocks = new Stocks(); test('if we know Bill stock, sell apples to him', () => { stocks.sync('Bill'); expect(stocks.getInfo('Bill')).toBeTruthy(); });
En JavaScript, todo se evalúa como verdadero, excepto
false
,0
,''
,null
,undefined
yNaN
.
toBeFalsy
Tipo:
() => Awaitable<void>
toBeFalsy
afirma que el valor es falso cuando se convierte a booleano. Útil si no importa el valor en sí, sino solo si se evalúa comofalse
en un contexto booleano.Por ejemplo, si tiene este código, no le importa el valor de retorno de
stocks.stockFailed
: puede devolver cualquier valor falso, pero el código seguirá funcionando.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (!stocks.stockFailed('Bill')) stocks.sell('apples', 'Bill');
Por lo tanto, si desea probar que
stocks.stockFailed
será falso, podría escribir:tsimport { expect, test } from 'vitest'; import { Stocks } from './stocks.js'; const stocks = new Stocks(); test("if Bill stock hasn't failed, sell apples to him", () => { stocks.syncStocks('Bill'); expect(stocks.stockFailed('Bill')).toBeFalsy(); });
En JavaScript, todo se evalúa como verdadero, excepto
false
,0
,''
,null
,undefined
yNaN
.
toBeNull
Tipo:
() => Awaitable<void>
toBeNull
simplemente afirma si algo esnull
. Alias para.toBe(null)
.tsimport { expect, test } from 'vitest'; function apples() { return null; } test("we don't have apples", () => { expect(apples()).toBeNull(); });
toBeNaN
Tipo:
() => Awaitable<void>
toBeNaN
simplemente afirma si algo esNaN
. Alias para.toBe(NaN)
.tsimport { expect, test } from 'vitest'; let i = 0; function getApplesCount() { i++; return i > 1 ? Number.NaN : i; } test('getApplesCount has some unusual side effects...', () => { expect(getApplesCount()).not.toBeNaN(); expect(getApplesCount()).toBeNaN(); });
toBeTypeOf
Tipo:
(c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>
toBeTypeOf
comprueba si un valor es del tipo especificado.tsimport { expect, test } from 'vitest'; const actual = 'stock'; test('stock is type of string', () => { expect(actual).toBeTypeOf('string'); });
toBeInstanceOf
Tipo:
(c: any) => Awaitable<void>
toBeInstanceOf
comprueba si un valor es una instancia de la clase especificada.tsimport { expect, test } from 'vitest'; import { Stocks } from './stocks.js'; const stocks = new Stocks(); test('stocks are instance of Stocks', () => { expect(stocks).toBeInstanceOf(Stocks); });
toBeGreaterThan
Tipo:
(n: number | bigint) => Awaitable<void>
toBeGreaterThan
afirma si el valor real es mayor que el recibido. La prueba fallará si los valores son iguales.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have more then 10 apples', () => { expect(getApples()).toBeGreaterThan(10); });
toBeGreaterThanOrEqual
Tipo:
(n: number | bigint) => Awaitable<void>
toBeGreaterThanOrEqual
afirma si el valor real es mayor o igual que el recibido.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have 11 apples or more', () => { expect(getApples()).toBeGreaterThanOrEqual(11); });
toBeLessThan
Tipo:
(n: number | bigint) => Awaitable<void>
toBeLessThan
afirma si el valor real es menor que el recibido. La prueba fallará si los valores son iguales.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have less then 20 apples', () => { expect(getApples()).toBeLessThan(20); });
toBeLessThanOrEqual
Tipo:
(n: number | bigint) => Awaitable<void>
toBeLessThanOrEqual
afirma si el valor real es menor o igual que el recibido.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have 11 apples or less', () => { expect(getApples()).toBeLessThanOrEqual(11); });
toEqual
Tipo:
(received: any) => Awaitable<void>
toEqual
afirma si el valor real es igual al recibido o tiene la misma estructura, si es un objeto (comparación recursiva). Puede ver la diferencia entretoEqual
ytoBe
en este ejemplo:tsimport { expect, test } from 'vitest'; const stockBill = { type: 'apples', count: 13, }; const stockMary = { type: 'apples', count: 13, }; test('stocks have the same properties', () => { expect(stockBill).toEqual(stockMary); }); test('stocks are not the same', () => { expect(stockBill).not.toBe(stockMary); });
WARNING
No se realizará una igualdad profunda para los objetos
Error
. Para probar si se lanzó algo, utilice la asercióntoThrowError
.
toStrictEqual
Tipo:
(received: any) => Awaitable<void>
toStrictEqual
afirma si el valor real es igual al recibido o tiene la misma estructura si es un objeto (comparación recursiva) y del mismo tipo.Diferencias con
.toEqual
:- Se verifican las propiedades con valor
undefined
. Por ejemplo,{a: undefined, b: 2}
no coincide con{ b: 2 }
cuando se utiliza.toStrictEqual
. - Se verifica la dispersión en arrays. Por ejemplo,
[, 1]
no coincide con[ undefined, 1 ]
cuando se utiliza.toStrictEqual
. - Se verifica que los tipos de objeto coincidan. Por ejemplo, una instancia de clase con los campos
a
yb
no será igual a un objeto literal con los camposa
yb
.
tsimport { expect, test } from 'vitest'; class Stock { constructor(type) { this.type = type; } } test('structurally the same, but semantically different', () => { expect(new Stock('apples')).toEqual({ type: 'apples' }); expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' }); });
- Se verifican las propiedades con valor
toContain
Tipo:
(received: string) => Awaitable<void>
toContain
comprueba si un valor está presente en un array.toContain
también puede comprobar si una cadena es una subcadena de otra cadena.tsimport { expect, test } from 'vitest'; import { getAllFruits } from './stocks.js'; test('the fruit list contains orange', () => { expect(getAllFruits()).toContain('orange'); });
toContainEqual
Tipo:
(received: any) => Awaitable<void>
toContainEqual
afirma si un elemento con una estructura y valores específicos está contenido en un arreglo. Realiza una comparación similar atoEqual
para cada elemento del array.tsimport { expect, test } from 'vitest'; import { getFruitStock } from './stocks.js'; test('apple available', () => { expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 }); });
toHaveLength
Tipo:
(received: number) => Awaitable<void>
toHaveLength
comprueba si la propiedad.length
de un objeto coincide con un valor numérico específico.tsimport { expect, test } from 'vitest'; test('toHaveLength', () => { expect('abc').toHaveLength(3); expect([1, 2, 3]).toHaveLength(3); expect('').not.toHaveLength(3); // no tiene longitud (.length) de 3 expect({ length: 3 }).toHaveLength(3); });
toHaveProperty
Tipo:
(key: any, received?: any) => Awaitable<void>
toHaveProperty
verifica si un objeto tiene una propiedad con la clavekey
proporcionada.Opcionalmente, puedes proporcionar un argumento de valor, similar al matcher
toEqual
, para comparar el valor de la propiedad.tsimport { expect, test } from 'vitest'; const invoice = { isActive: true, 'P.O': '12345', customer: { first_name: 'John', last_name: 'Doe', location: 'China', }, total_amount: 5000, items: [ { type: 'apples', quantity: 10, }, { type: 'oranges', quantity: 5, }, ], }; test('John Doe Invoice', () => { expect(invoice).toHaveProperty('isActive'); // Verifica que la clave existe expect(invoice).toHaveProperty('total_amount', 5000); // Verifica que la clave existe y el valor coincide expect(invoice).not.toHaveProperty('account'); // Verifica que la clave no existe. // Referencia profunda usando notación de puntos expect(invoice).toHaveProperty('customer.first_name'); expect(invoice).toHaveProperty('customer.last_name', 'Doe'); expect(invoice).not.toHaveProperty('customer.location', 'India'); // Referencia profunda usando un array que contiene la clave expect(invoice).toHaveProperty('items[0].type', 'apples'); expect(invoice).toHaveProperty('items.0.type', 'apples'); // La notación de puntos también es válida. // Referencia profunda usando un array que contiene el keyPath expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples'); expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // La notación de string también es válida. // Envuelve tu clave en un array para evitar que la clave se analice como una referencia profunda expect(invoice).toHaveProperty(['P.O'], '12345'); });
toMatch
Tipo:
(received: string | regexp) => Awaitable<void>
toMatch
verifica si una cadena coincide con una expresión regular o con otra cadena.tsimport { expect, test } from 'vitest'; test('top fruits', () => { expect('top fruits include apple, orange and grape').toMatch(/apple/); expect('applefruits').toMatch('fruit'); // toMatch también acepta una cadena });
TIP
Si el valor en el mensaje de error aparece truncado, puedes aumentar chaiConfig.truncateThreshold en tu archivo de configuración.
toMatchObject
Tipo:
(received: object | array) => Awaitable<void>
toMatchObject
verifica si un objeto coincide con un subconjunto de las propiedades de otro objeto.También puedes pasar un array de objetos. Esto es útil para comprobar que dos arrays coinciden exactamente en el número de elementos, a diferencia de
arrayContaining
, que permite elementos adicionales en el array recibido.tsimport { expect, test } from 'vitest'; const johnInvoice = { isActive: true, customer: { first_name: 'John', last_name: 'Doe', location: 'China', }, total_amount: 5000, items: [ { type: 'apples', quantity: 10, }, { type: 'oranges', quantity: 5, }, ], }; const johnDetails = { customer: { first_name: 'John', last_name: 'Doe', location: 'China', }, }; test('invoice has john personal details', () => { expect(johnInvoice).toMatchObject(johnDetails); }); test('the number of elements must match exactly', () => { // Comprueba que un array de objetos coincide expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([ { foo: 'bar' }, { baz: 1 }, ]); });
toThrowError
Tipo:
(received: any) => Awaitable<void>
Alias:
toThrow
toThrowError
verifica si una función lanza un error cuando se ejecuta.Puedes proporcionar un argumento opcional para verificar que se lanza un error específico:
- expresión regular: el mensaje de error coincide con el patrón
- cadena: el mensaje de error incluye la subcadena
TIP
Debes envolver el código en una función; de lo contrario, el error no se capturará y la prueba fallará.
Por ejemplo, si queremos probar que
getFruitStock('pineapples')
lanza un error, podríamos escribir:tsimport { expect, test } from 'vitest'; function getFruitStock(type) { if (type === 'pineapples') throw new DiabetesError( 'Pineapples are not good for people with diabetes' ); // Do some other stuff } test('throws on pineapples', () => { // Comprueba que el mensaje de error contiene "diabetes" en alguna parte: estos son equivalentes expect(() => getFruitStock('pineapples')).toThrowError(/diabetes/); expect(() => getFruitStock('pineapples')).toThrowError('diabetes'); // Prueba el mensaje de error exacto expect(() => getFruitStock('pineapples')).toThrowError( /^Pineapples are not good for people with diabetes$/ ); });
TIP
Para probar funciones asíncronas, úsalo en combinación con rejects.
jsfunction getAsyncFruitStock() { return Promise.reject(new Error('empty')); } test('throws on pineapples', async () => { await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty'); });
toMatchSnapshot
Tipo:
<T>(shape?: Partial<T> | string, message?: string) => void
Asegura que un valor coincida con la última instantánea.
Puedes proporcionar un argumento de cadena
hint
opcional que se agrega al nombre de la prueba. Aunque Vitest siempre agrega un número al final de un nombre de instantánea, las sugerencias descriptivas breves pueden ser más útiles que los números para diferenciar múltiples instantáneas en un solo bloqueit
otest
. Vitest ordena las instantáneas por nombre en el archivo.snap
correspondiente.TIP
Cuando la instantánea no coincide y causa que la prueba falle, si este desajuste es esperado, puedes presionar la tecla
u
para actualizar la instantánea manualmente. O puedes pasar las opciones de CLI-u
o--update
para hacer que Vitest siempre actualice las pruebas.tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchSnapshot(); });
También puedes proporcionar una forma de un objeto, si estás probando solo una forma de un objeto, y no necesitas que sea 100% compatible:
tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchSnapshot({ foo: expect.any(Set) }); });
toMatchInlineSnapshot
Tipo:
<T>(shape?: Partial<T> | string, snapshot?: string, message?: string) => void
Asegura que un valor coincida con la última instantánea.
Vitest agrega y actualiza el argumento de cadena
inlineSnapshot
al matcher en el archivo de prueba (en lugar de un archivo.snap
externo).tsimport { expect, test } from 'vitest'; test('matches inline snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; // Vitest will update following content when updating the snapshot expect(data).toMatchInlineSnapshot(` { "foo": Set { "bar", "snapshot", }, } `); });
También puedes proporcionar una forma de un objeto, si estás probando solo una forma de un objeto, y no necesitas que sea 100% compatible:
tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchInlineSnapshot( { foo: expect.any(Set) }, ` { "foo": Any<Set>, } ` ); });
toMatchFileSnapshot
Tipo:
<T>(filepath: string, message?: string) => Promise<void>
Versión: Desde Vitest 0.30.0
Compara o actualiza la instantánea con el contenido de un archivo especificado explícitamente (en lugar del archivo
.snap
).tsimport { expect, it } from 'vitest'; it('render basic', async () => { const result = renderHTML(h('div', { class: 'foo' })); await expect(result).toMatchFileSnapshot('./test/basic.output.html'); });
Ten en cuenta que, dado que la operación del sistema de archivos es asíncrona, debes usar
await
contoMatchFileSnapshot()
.
toThrowErrorMatchingSnapshot
Tipo:
(message?: string) => void
Similar a
toMatchSnapshot
, pero espera el mismo valor quetoThrowError
.Si la función lanza un
Error
, la instantánea será el mensaje de error. De lo contrario, la instantánea será el valor lanzado por la función.
toThrowErrorMatchingInlineSnapshot
Tipo:
(snapshot?: string, message?: string) => void
Similar a
toMatchInlineSnapshot
, pero espera el mismo valor quetoThrowError
.Si la función lanza un
Error
, la instantánea será el mensaje de error. De lo contrario, la instantánea será el valor lanzado por la función.
toHaveBeenCalled
Tipo:
() => Awaitable<void>
Esta afirmación es útil para verificar si una función ha sido llamada. Requiere que se pase una función espía a
expect
.tsimport { expect, test, vi } from 'vitest'; const market = { buy(subject: string, amount: number) { // ... }, }; test('spy function', () => { const buySpy = vi.spyOn(market, 'buy'); expect(buySpy).not.toHaveBeenCalled(); market.buy('apples', 10); expect(buySpy).toHaveBeenCalled(); });
toHaveBeenCalledTimes
- Tipo:
(amount: number) => Awaitable<void>
Esta afirmación comprueba si una función fue llamada una cantidad específica de veces. Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('spy function called two times', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).toHaveBeenCalledTimes(2);
});
toHaveBeenCalledWith
- Tipo:
(...args: any[]) => Awaitable<void>
Esta afirmación comprueba si una función fue llamada al menos una vez con ciertos parámetros. Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('spy function', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).toHaveBeenCalledWith('apples', 10);
expect(buySpy).toHaveBeenCalledWith('apples', 20);
});
toHaveBeenLastCalledWith
- Tipo:
(...args: any[]) => Awaitable<void>
Esta afirmación comprueba si una función fue llamada con ciertos parámetros en su última invocación. Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('spy function', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).not.toHaveBeenLastCalledWith('apples', 10);
expect(buySpy).toHaveBeenLastCalledWith('apples', 20);
});
toHaveBeenNthCalledWith
- Tipo:
(time: number, ...args: any[]) => Awaitable<void>
Esta afirmación comprueba si una función fue llamada con ciertos parámetros en una invocación específica. El conteo comienza en 1. Por lo tanto, para verificar la segunda llamada, usarías .toHaveBeenNthCalledWith(2, ...)
.
Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('first call of spy function called with right params', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).toHaveBeenNthCalledWith(1, 'apples', 10);
});
toHaveReturned
- Tipo:
() => Awaitable<void>
Esta afirmación comprueba si una función ha devuelto un valor correctamente al menos una vez (es decir, no lanzó un error). Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
function getApplesPrice(amount: number) {
const PRICE = 10;
return amount * PRICE;
}
test('spy function returned a value', () => {
const getPriceSpy = vi.fn(getApplesPrice);
const price = getPriceSpy(10);
expect(price).toBe(100);
expect(getPriceSpy).toHaveReturned();
});
toHaveReturnedTimes
- Tipo:
(amount: number) => Awaitable<void>
Esta afirmación comprueba si una función ha devuelto un valor correctamente una cantidad exacta de veces (es decir, no lanzó un error). Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
test('spy function returns a value two times', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveReturnedTimes(2);
});
toHaveReturnedWith
- Tipo:
(returnValue: any) => Awaitable<void>
Puedes usar esta aserción para verificar si una función espía (spy function) ha retornado un valor específico al menos una vez. Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
test('la función espía retorna un producto', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
expect(sell).toHaveReturnedWith({ product: 'apples' });
});
toHaveLastReturnedWith
- Tipo:
(returnValue: any) => Awaitable<void>
Puedes usar esta aserción para verificar si una función espía (spy function) ha retornado un valor específico en su última invocación. Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
test('la función espía retorna bananas en la última llamada', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});
toHaveNthReturnedWith
- Tipo:
(time: number, returnValue: any) => Awaitable<void>
Puedes usar esta aserción para verificar si una función espía (spy function) ha retornado un valor específico en una invocación determinada. Requiere que se pase una función espía a expect
.
import { expect, test, vi } from 'vitest';
test('la función espía retorna bananas en la segunda llamada', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' });
});
toSatisfy
- Tipo:
(predicate: (value: any) => boolean) => Awaitable<void>
Esta aserción verifica si un valor cumple con un predicado dado.
describe('toSatisfy()', () => {
const isOdd = (value: number) => value % 2 !== 0;
it('pasa con 1', () => {
expect(1).toSatisfy(isOdd);
});
it('pasa con negación', () => {
expect(2).not.toSatisfy(isOdd);
});
});
resolves
Tipo:
Promisify<Assertions>
resolves
está diseñado para simplificar las aserciones en código asíncrono. Úsalo para extraer el valor resuelto de una promesa y realizar una aserción sobre ese valor utilizando las aserciones habituales. Si la promesa es rechazada, la aserción fallará.Retorna el mismo objeto
Assertions
, pero todos los matchers ahora retornanPromise
, por lo que necesitarás usarawait
. También funciona con aserciones dechai
.Por ejemplo, si tienes una función que realiza una llamada a una API y retorna datos, puedes usar este código para realizar una aserción sobre su valor de retorno:
tsimport { expect, test } from 'vitest'; async function buyApples() { return fetch('/buy/apples').then(r => r.json()); } test('buyApples retorna el nuevo ID del stock', async () => { // toEqual retorna una promesa ahora, así que debes usar await await expect(buyApples()).resolves.toEqual({ id: 1 }); // API de Jest await expect(buyApples()).resolves.to.equal({ id: 1 }); // API de Chai });
WARNING
Si no esperas la aserción con
await
, tendrás una prueba falsamente positiva que siempre pasará. Para asegurarte de que las aserciones se ejecuten realmente, puedes usarexpect.assertions(number)
.
rejects
Tipo:
Promisify<Assertions>
rejects
está diseñado para simplificar las aserciones en código asíncrono. Úsalo para extraer la razón por la cual una promesa fue rechazada y realizar una aserción sobre ese valor utilizando las aserciones habituales. Si la promesa se resuelve exitosamente, la aserción fallará.Retorna el mismo objeto
Assertions
, pero todos los matchers ahora retornanPromise
, por lo que necesitarás usarawait
. También funciona con aserciones dechai
.Por ejemplo, si tienes una función que falla cuando la llamas, puedes usar este código para realizar una aserción sobre la razón del rechazo:
tsimport { expect, test } from 'vitest'; async function buyApples(id) { if (!id) throw new Error('no id'); } test('buyApples lanza un error cuando no se proporciona un ID', async () => { // toThrow retorna una promesa ahora, así que debes usar await await expect(buyApples()).rejects.toThrow('no id'); });
WARNING
Si no esperas la aserción con
await
, tendrás una prueba falsamente positiva que siempre pasará. Para asegurarte de que las aserciones se ejecuten realmente, puedes usarexpect.assertions(number)
.
expect.assertions
Tipo:
(count: number) => void
Después de que la prueba haya finalizado (ya sea pasando o fallando), verifica que se haya llamado a un número específico de aserciones durante la prueba. Un caso de uso común es verificar si se ejecutó código asíncrono.
Por ejemplo, si tenemos una función que llama asíncronamente a dos matchers, podemos asegurar que ambos fueron realmente llamados.
tsimport { expect, test } from 'vitest'; async function doAsync(...cbs) { await Promise.all(cbs.map((cb, index) => cb({ index }))); } test('todas las aserciones son llamadas', async () => { expect.assertions(2); function callback1(data) { expect(data).toBeTruthy(); } function callback2(data) { expect(data).toBeTruthy(); } await doAsync(callback1, callback2); });
WARNING
Cuando se usa
assertions
con pruebas concurrentes asíncronas, elexpect
del Contexto de Prueba local debe ser usado para asegurar que la prueba correcta sea detectada.
expect.hasAssertions
Tipo:
() => void
Después de que la prueba haya finalizado (ya sea pasando o fallando), verifica que se haya llamado al menos a una aserción durante la prueba. Un caso de uso común es verificar si se ejecutó código asíncrono.
Por ejemplo, si tienes un código que llama a un callback, podemos hacer una aserción dentro del callback, pero la prueba siempre pasará si no verificamos si se llamó a alguna aserción.
tsimport { expect, test } from 'vitest'; import { db } from './db.js'; const cbs = []; function onSelect(cb) { cbs.push(cb); } // después de seleccionar de la base de datos, llamamos a todos los callbacks function select(id) { return db.select({ id }).then(data => { return Promise.all(cbs.map(cb => cb(data))); }); } test('el callback fue llamado', async () => { expect.hasAssertions(); onSelect(data => { // debería ser llamado en la selección expect(data).toBeTruthy(); }); // si no se espera con await, la prueba fallará // si no tienes expect.hasAssertions(), la prueba pasará await select(3); });
expect.unreachable
Tipo:
(message?: string) => never
Este método se usa para asegurar que una línea de código nunca debería ser alcanzada.
Por ejemplo, si queremos probar que
build()
lanza un error porque los directorios recibidos no tienen una carpetasrc
, y también manejar cada error por separado, podríamos hacer esto:tsimport { expect, test } from 'vitest'; async function build(dir) { if (dir.includes('no-src')) throw new Error(`${dir}/src does not exist`); } const errorDirs = [ 'no-src-folder', // ... ]; test.each(errorDirs)('build falla con "%s"', async dir => { try { await build(dir); expect.unreachable('No debería pasar la compilación'); // No debería completarse la compilación } catch (err: any) { expect(err).toBeInstanceOf(Error); expect(err.stack).toContain('build'); switch (dir) { case 'no-src-folder': expect(err.message).toBe(`${dir}/src does not exist`); break; default: // para agotar todas las pruebas de error expect.unreachable( 'Todas las pruebas de error deben ser gestionadas' ); // Todas las pruebas de error deben ser gestionadas break; } } });
expect.anything
Tipo:
() => any
Este matcher asimétrico, cuando se usa en una verificación de igualdad, siempre retornará
true
. Es útil si solo quieres asegurarte de que una propiedad existe.tsimport { expect, test } from 'vitest'; test('el objeto tiene la clave "apples"', () => { expect({ apples: 22 }).toEqual({ apples: expect.anything() }); });
expect.any
Tipo:
(constructor: unknown) => any
Este matcher asimétrico, cuando se usa en una verificación de igualdad, devolverá
true
solo si el valor es una instancia del constructor especificado. Es útil si tienes un valor que se genera cada vez y solo quieres saber que existe con el tipo apropiado.tsimport { expect, test } from 'vitest'; import { generateId } from './generators.js'; test('"id" es un número', () => { expect({ id: generateId() }).toEqual({ id: expect.any(Number) }); });
expect.arrayContaining
Tipo:
<T>(expected: T[]) => any
Cuando se usa en una verificación de igualdad, este matcher asimétrico retornará
true
si el valor es un array y contiene los elementos especificados.tsimport { expect, test } from 'vitest'; test('la cesta incluye fuji', () => { const basket = { varieties: ['Empire', 'Fuji', 'Gala'], count: 3, }; expect(basket).toEqual({ count: 3, varieties: expect.arrayContaining(['Fuji']), }); });
TIP
Puedes usar
expect.not
con este matcher para negar el valor esperado.
expect.objectContaining
Tipo:
(expected: any) => any
Cuando se usa en una verificación de igualdad, este matcher asimétrico retornará
true
si el valor tiene una estructura similar.tsimport { expect, test } from 'vitest'; test('la cesta tiene manzanas empire', () => { const basket = { varieties: [ { name: 'Empire', count: 1, }, ], }; expect(basket).toEqual({ varieties: [expect.objectContaining({ name: 'Empire' })], }); });
TIP
Puedes usar
expect.not
con este matcher para negar el valor esperado.
expect.stringContaining
Tipo:
(expected: any) => any
Cuando se usa en una verificación de igualdad, este matcher asimétrico retornará
true
si el valor es un string y contiene una subcadena especificada.tsimport { expect, test } from 'vitest'; test('la variedad tiene "Emp" en su nombre', () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringContaining('Emp'), count: 1, }); });
TIP
Puedes usar
expect.not
con este matcher para negar el valor esperado.
expect.stringMatching
Tipo:
(expected: any) => any
Cuando se usa en una verificación de igualdad, este matcher asimétrico retornará
true
si el valor es un string y contiene una subcadena especificada o si el string coincide con una expresión regular.tsimport { expect, test } from 'vitest'; test('la variedad termina con "re"', () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringMatching(/re$/), count: 1, }); });
TIP
Puedes usar
expect.not
con este matcher para negar el valor esperado.
expect.addSnapshotSerializer
Tipo:
(plugin: PrettyFormatPlugin) => void
Este método agrega serializadores personalizados que se invocan al crear una instantánea (snapshot). Esta es una característica avanzada; si quieres saber más, consulta la guía sobre serializadores personalizados.
Si estás agregando serializadores personalizados, deberías invocar este método dentro de
setupFiles
. Esto afectará a cada instantánea.TIP
Si previamente usaste Vue CLI con Jest, es posible que desees instalar jest-serializer-vue. De lo contrario, tus instantáneas se envolverán en una cadena, lo que provocará que se escape
"
."
expect.extend
Tipo:
(matchers: MatchersObject) => void
Puedes extender los matchers predeterminados con los tuyos propios. Esta función se usa para extender el objeto de matchers con matchers personalizados.
Cuando defines matchers de esta manera, también creas matchers asimétricos que se pueden usar como
expect.stringContaining
.tsimport { expect, test } from 'vitest'; test('matchers personalizados', () => { expect.extend({ toBeFoo: (received, expected) => { if (received !== 'foo') { return { message: () => `se esperaba que ${received} fuera foo`, pass: false, }; } }, }); expect('foo').toBeFoo(); expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() }); });
TIP
Si quieres que tus matchers aparezcan en cada prueba, deberías invocar este método dentro de
setupFiles
.Esta función es compatible con
expect.extend
de Jest, por lo que cualquier librería que lo use para crear matchers personalizados funcionará con Vitest.Si estás usando TypeScript, a partir de Vitest 0.31.0 puedes extender la interfaz
Assertion
predeterminada en un archivo de declaración de entorno (p. ej.,vitest.d.ts
) con el siguiente código:tsinterface CustomMatchers<R = unknown> { toBeFoo(): R; } declare module 'vitest' { interface Assertion<T = any> extends CustomMatchers<T> {} interface AsymmetricMatchersContaining extends CustomMatchers {} }
WARNING
No olvides incluir el archivo de declaración en tu
tsconfig.json
.TIP
Si quieres saber más, revisa la guía sobre cómo extender matchers.