expect
Os seguintes tipos são usados nas assinaturas de tipo abaixo:
type Awaitable<T> = T | PromiseLike<T>;
expect
é usado para criar asserções. Neste contexto, asserções
são funções que podem ser chamadas para garantir uma condição. O Vitest fornece asserções chai
por padrão e também asserções compatíveis com Jest
construídas sobre o chai
.
Por exemplo, este código garante que um valor input
é igual a 2
. Se não for, a asserção lançará um erro e o teste falhará.
import { expect } from 'vitest';
const input = Math.sqrt(4);
expect(input).to.equal(2); // API chai
expect(input).toBe(2); // API jest
Tecnicamente, esse exemplo não usa a função test
, então você verá o erro do Node.js no console em vez da saída do Vitest. Para saber mais sobre test
, consulte a Referência da API de Teste.
Além disso, expect
pode ser usado estaticamente para acessar os matchers (descritos posteriormente) e muito mais.
WARNING
expect
não tem efeito na tipagem dos testes, a menos que a expressão tenha um erro de tipo. Se você quiser usar o Vitest como verificador de tipo, use expectTypeOf
ou assertType
.
soft
- Tipo:
ExpectStatic & (actual: any) => Assertions
expect.soft
funciona de forma semelhante a expect
, mas em vez de interromper a execução do teste após uma asserção falhar, ele continua executando e marca o teste como falho. Todos os erros encontrados durante o teste serão exibidos ao final da execução.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // marca o teste como falha e continua
expect.soft(1 + 2).toBe(4); // marca o teste como falha e continua
});
// Ao final do teste, os erros acima serão exibidos.
Ele também pode ser usado em conjunto com expect
. Se a asserção expect
falhar, o teste será interrompido e todos os erros serão exibidos.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // marca o teste como falha e continua
expect(1 + 2).toBe(3); // falha e interrompe o teste, todos os erros anteriores serão exibidos
expect.soft(1 + 2).toBe(4); // não executa
});
WARNING
expect.soft
só pode ser usado dentro da função test
.
not
Usar not
irá negar a asserção. Por exemplo, este código garante que um valor input
não é igual a 2
. Se for igual, a asserção lançará um erro e o teste falhará.
import { expect, test } from 'vitest';
const input = Math.sqrt(16);
expect(input).not.to.equal(2); // API chai
expect(input).not.toBe(2); // API jest
toBe
Tipo:
(value: any) => Awaitable<void>
toBe
pode ser usado para verificar se primitivos são iguais ou se objetos compartilham a mesma referência. É o mesmo que chamarexpect(Object.is(3, 3)).toBe(true)
. Se os objetos não forem os mesmos, mas você quiser verificar se suas estruturas são idênticas, você pode usartoEqual
.Por exemplo, o código abaixo verifica se o comerciante tem 13 maçãs.
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; // mesma referência expect(stock).toBe(refStock); });
Evite usar
toBe
com números de ponto flutuante. Como o JavaScript os arredonda,0.1 + 0.2
não é estritamente0.3
. Para garantir a comparação de números de ponto flutuante de forma confiável, use a asserçãotoBeCloseTo
.
toBeCloseTo
Tipo:
(value: number, numDigits?: number) => Awaitable<void>
Use
toBeCloseTo
para comparar números de ponto flutuante. O argumento opcionalnumDigits
limita o número de dígitos para verificar após o ponto decimal. Por exemplo: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 é 0.30000000000000004 }); test('decimals are rounded to 5 after the point', () => { // 0.2 + 0.1 é 0.30000 | "000000000004" removido expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // nada de 0.30000000000000004 é removido expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50); });
toBeDefined
Tipo:
() => Awaitable<void>
toBeDefined
garante que o valor não é igual aundefined
. Um caso de uso útil é verificar se a função retornou algum valor.tsimport { expect, test } from 'vitest'; function getApples() { return 3; } test('function returned something', () => { expect(getApples()).toBeDefined(); });
toBeUndefined
Tipo:
() => Awaitable<void>
O oposto de
toBeDefined
,toBeUndefined
garante que o valor é igual aundefined
. Um caso de uso útil é verificar se a função não retornou nada.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
garante que o valor é verdadeiro quando convertido para booleano. Útil se você não se importa com o valor retornado, mas apenas quer saber se ele pode ser convertido paratrue
.Por exemplo, com este código, você não se importa com o valor de retorno de
stocks.getInfo
- pode ser um objeto complexo, uma string ou qualquer outra coisa. O código ainda funcionará.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (stocks.getInfo('Bill')) stocks.sell('apples', 'Bill');
Então, se você quiser testar se
stocks.getInfo
será truthy, você pode escrever: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(); });
Tudo em JavaScript é truthy, exceto
false
,0
,''
,null
,undefined
eNaN
.
toBeFalsy
Tipo:
() => Awaitable<void>
toBeFalsy
garante que o valor é falso quando convertido para booleano. Útil se você não se importa com o valor retornado, mas apenas quer saber se ele pode ser convertido parafalse
.Por exemplo, com este código, você não se importa com o valor de retorno de
stocks.stockFailed
- ele pode retornar qualquer valor falsy, mas o código ainda funcionará.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (!stocks.stockFailed('Bill')) stocks.sell('apples', 'Bill');
Então, se você quiser testar se
stocks.stockFailed
será falsy, você pode escrever: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(); });
Tudo em JavaScript é truthy, exceto
false
,0
,''
,null
,undefined
eNaN
.
toBeNull
Tipo:
() => Awaitable<void>
toBeNull
simplesmente garante se algo énull
. 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
simplesmente garante se algo éNaN
. 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
verifica se um valor é do 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
verifica se um valor é uma instância da classe 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
verifica se o valor é maior que o valor esperado. Valores iguais farão o teste falhar.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
garante se o valor real é maior ou igual ao valor recebido.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
garante se o valor real é menor que o valor recebido. Valores iguais farão o teste falhar.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
garante se o valor real é menor ou igual ao valor recebido.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
verifica se o valor é igual ao valor esperado ou se tem a mesma estrutura (comparando-os recursivamente, se forem objetos). Você pode ver a diferença entretoEqual
etoBe
neste exemplo: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
Uma comparação profunda não será realizada para objetos
Error
. Para testar se algo foi lançado, use a asserçãotoThrowError
.
toStrictEqual
Tipo:
(received: any) => Awaitable<void>
toStrictEqual
verifica se o valor é igual ao valor esperado, tem a mesma estrutura (comparando-os recursivamente, se forem objetos) e é do mesmo tipo.Diferenças de
.toEqual
:- As chaves com propriedades
undefined
são verificadas. ex.{a: undefined, b: 2}
não corresponde a{b: 2}
ao usar.toStrictEqual
. - A dispersão do array é verificada. ex.
[, 1]
não corresponde a[undefined, 1]
ao usar.toStrictEqual
. - Os tipos de objeto são verificados para serem iguais. ex. Uma instância de classe com campos
a
eb
não será igual a um objeto literal com camposa
eb
.
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' }); });
- As chaves com propriedades
toContain
Tipo:
(received: string) => Awaitable<void>
toContain
verifica se o valor está presente em um array.toContain
também pode verificar se uma string é uma substring de outra string.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
verifica se um item com a estrutura e os valores especificados está presente em um array. Funciona comotoEqual
para cada elemento.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
garante se um objeto tem uma propriedade.length
e ela está definida como um determinado valor numérico.tsimport { expect, test } from 'vitest'; test('toHaveLength', () => { expect('abc').toHaveLength(3); expect([1, 2, 3]).toHaveLength(3); expect('').not.toHaveLength(3); // não tem .length de 3 expect({ length: 3 }).toHaveLength(3); });
toHaveProperty
Tipo:
(key: any, received?: any) => Awaitable<void>
toHaveProperty
verifica se um objeto possui uma propriedade com a chavekey
especificada.Você pode fornecer um argumento de valor opcional, usando igualdade profunda (deep equality), similar ao matcher
toEqual
, para comparar o valor da propriedade.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'); // Afirma que a propriedade existe expect(invoice).toHaveProperty('total_amount', 5000); // Afirma que a propriedade existe e o valor é igual expect(invoice).not.toHaveProperty('account'); // Afirma que esta propriedade não existe // Acesso profundo usando notação de ponto expect(invoice).toHaveProperty('customer.first_name'); // Afirma que a propriedade 'customer.first_name' existe expect(invoice).toHaveProperty('customer.last_name', 'Doe'); expect(invoice).not.toHaveProperty('customer.location', 'India'); // Acesso profundo usando um array contendo a chave expect(invoice).toHaveProperty('items[0].type', 'apples'); expect(invoice).toHaveProperty('items.0.type', 'apples'); // A notação de ponto também funciona // Acesso profundo usando um array contendo o caminho da chave expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples'); expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // A notação de string também funciona // Use um array para envolver sua chave para evitar que ela seja interpretada como um caminho de acesso profundo expect(invoice).toHaveProperty(['P.O'], '12345'); });
toMatch
Tipo:
(received: string | regexp) => Awaitable<void>
toMatch
verifica se uma string corresponde a uma expressão regular ou a outra string.tsimport { expect, test } from 'vitest'; test('top fruits', () => { expect('top fruits include apple, orange and grape').toMatch(/apple/); expect('applefruits').toMatch('fruit'); // toMatch também aceita uma string });
TIP
Se o valor na mensagem de erro estiver truncado, você pode aumentar o valor de chaiConfig.truncateThreshold
no seu arquivo de configuração. Consulte chaiConfig.truncateThreshold.
toMatchObject
Tipo:
(received: object | array) => Awaitable<void>
toMatchObject
verifica se um objeto corresponde a um subconjunto das propriedades de outro objeto.É útil para verificar se dois arrays têm o mesmo número de elementos e se os elementos correspondem, diferentemente de
arrayContaining
, que permite elementos adicionais no array recebido.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', () => { // Verifica se um array de objetos corresponde expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([ { foo: 'bar' }, { baz: 1 }, ]); });
toThrowError
Tipo:
(received: any) => Awaitable<void>
Alias:
toThrow
toThrowError
verifica se uma função lança um erro quando invocada.Você pode fornecer um argumento opcional para testar se um tipo específico de erro é lançado:
- expressão regular: a mensagem de erro corresponde ao padrão
- string: a mensagem de erro inclui a substring
TIP
Você deve envolver o código em uma função; caso contrário, o erro não será capturado e o teste falhará.
Por exemplo, se quisermos testar se
getFruitStock('pineapples')
lança um erro, podemos escrever:tsimport { expect, test } from 'vitest'; function getFruitStock(type) { if (type === 'pineapples') throw new DiabetesError( 'Pineapples are not good for people with diabetes' ); // Faça outras coisas } test('throws on pineapples', () => { // Teste se a mensagem de erro contém "diabetes" em algum lugar: estes são equivalentes expect(() => getFruitStock('pineapples')).toThrowError(/diabetes/); expect(() => getFruitStock('pineapples')).toThrowError('diabetes'); // Teste a mensagem de erro exata expect(() => getFruitStock('pineapples')).toThrowError( /^Pineapples are not good for people with diabetes$/ ); });
TIP
Para testar funções assíncronas, use em combinação com 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
Garante que um valor corresponda ao snapshot mais recente.
Você pode fornecer um argumento de string
hint
(dica) opcional, que será anexado ao nome do teste. Embora o Vitest sempre anexe um número ao final de um nome de snapshot, dicas descritivas curtas podem ser mais úteis do que números para diferenciar vários snapshots em um único blocoit
outest
. O Vitest organiza os snapshots por nome no arquivo.snap
correspondente.TIP
Quando o snapshot não corresponde e causa a falha do teste, se a não correspondência for esperada, você pode pressionar a tecla
u
para atualizar o snapshot uma vez. Ou você pode usar as opções de linha de comando-u
ou--update
para que o Vitest sempre atualize os snapshots.tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchSnapshot(); });
Você também pode fornecer um formato (shape) de um objeto, se você estiver testando apenas um formato de um objeto e não precisar que ele seja 100% compatível:
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
Garante que um valor corresponda ao snapshot mais recente.
O Vitest adiciona e atualiza o argumento
inlineSnapshot
como uma string diretamente no arquivo de teste (em vez de um arquivo.snap
externo).tsimport { expect, test } from 'vitest'; test('matches inline snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; // O Vitest atualizará o seguinte conteúdo ao atualizar o snapshot expect(data).toMatchInlineSnapshot(` { "foo": Set { "bar", "snapshot", }, } `); });
Você também pode fornecer um formato (shape) de um objeto, se você estiver testando apenas um formato de um objeto e não precisar que ele seja 100% compatível:
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>
Versão: Desde Vitest 0.30.0
Compara ou atualiza o snapshot com o conteúdo de um arquivo explicitamente especificado (em vez do arquivo
.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'); });
Note que, por envolver operações assíncronas de sistema de arquivos, você precisa usar
await
comtoMatchFileSnapshot()
.
toThrowErrorMatchingSnapshot
Tipo:
(message?: string) => void
Similar a
toMatchSnapshot
, mas espera o mesmo valor quetoThrowError
.Se a função lançar um
Error
, o snapshot será a mensagem de erro. Caso contrário, o snapshot será o valor lançado pela função.
toThrowErrorMatchingInlineSnapshot
Tipo:
(snapshot?: string, message?: string) => void
Similar a
toMatchInlineSnapshot
, mas espera o mesmo valor quetoThrowError
.Se a função lançar um
Error
, o snapshot será a mensagem de erro. Caso contrário, o snapshot será o valor lançado pela função.
toHaveBeenCalled
Tipo:
() => Awaitable<void>
Esta asserção verifica se uma função foi chamada. Requer que uma função espia (spy) seja passada para
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 asserção verifica se uma função foi chamada um número específico de vezes. Requer que uma função espia (spy) seja passada para 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 asserção verifica se uma função foi chamada pelo menos uma vez com os parâmetros especificados. Requer que uma função espia (spy) seja passada para 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 asserção verifica se uma função foi chamada com os parâmetros especificados em sua última invocação. Requer que uma função espia (spy) seja passada para 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 asserção verifica se uma função foi chamada com os parâmetros especificados em um momento específico. A contagem começa em 1. Portanto, para verificar a segunda chamada, você usaria .toHaveBeenNthCalledWith(2, ...)
.
Requer que uma função espia (spy) seja passada para 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 asserção verifica se uma função retornou um valor com sucesso pelo menos uma vez (ou seja, não lançou um erro). Requer que uma função espia (spy) seja passada para 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 asserção verifica se uma função retornou um valor com sucesso a quantidade exata de vezes (ou seja, não lançou um erro). Requer que uma função espia (spy) seja passada para 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>
Você pode usar esta asserção para verificar se uma função retornou um valor específico com sucesso, pelo menos uma vez. Requer que uma função spy seja passada para expect
.
import { expect, test, vi } from 'vitest';
test('função spy retorna um produto', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
expect(sell).toHaveReturnedWith({ product: 'apples' });
});
toHaveLastReturnedWith
- Tipo:
(returnValue: any) => Awaitable<void>
Você pode usar esta asserção para verificar se uma função retornou um valor específico com sucesso na sua última invocação. Requer que uma função spy seja passada para expect
.
import { expect, test, vi } from 'vitest';
test('função spy retorna bananas na última chamada', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});
toHaveNthReturnedWith
- Tipo:
(time: number, returnValue: any) => Awaitable<void>
Você pode usar esta asserção para verificar se uma função retornou um valor específico com sucesso em uma chamada específica. Requer que uma função spy seja passada para expect
.
import { expect, test, vi } from 'vitest';
test('função spy retorna bananas na segunda chamada', () => {
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 asserção verifica se um valor satisfaz uma condição definida por um predicado.
describe('toSatisfy()', () => {
const isOdd = (value: number) => value % 2 !== 0;
it('passa com valor ímpar', () => {
expect(1).toSatisfy(isOdd);
});
it('passa com valor par (negação)', () => {
expect(2).not.toSatisfy(isOdd);
});
});
resolves
Tipo:
Promisify<Assertions>
resolves
simplifica o teste de código assíncrono. Use-o para extrair o valor de uma promise resolvida e validar seu valor com as asserções usuais. Se a promise for rejeitada, a asserção falhará.Ele retorna o mesmo objeto
Assertions
, mas todos os matchers agora retornamPromise
, então você precisará usarawait
neles. Também funciona com asserçõeschai
.Por exemplo, se você tem uma função que faz uma chamada de API e retorna alguns dados, você pode usar este código para validar o valor de retorno:
tsimport { expect, test } from 'vitest'; async function buyApples() { return fetch('/buy/apples').then(r => r.json()); } test('buyApples retorna o novo ID do estoque', async () => { // toEqual retorna uma promise agora, então você PRECISA usar await await expect(buyApples()).resolves.toEqual({ id: 1 }); // jest API await expect(buyApples()).resolves.to.equal({ id: 1 }); // chai API });
WARNING
Se a asserção não for aguardada, você terá um teste falso-positivo que sempre passará. Para garantir que as asserções sejam realmente chamadas, você pode usar
expect.assertions(number)
.
rejects
Tipo:
Promisify<Assertions>
rejects
simplifica o teste de código assíncrono. Use-o para extrair o motivo pelo qual a promise foi rejeitada e validar seu valor com as asserções usuais. Se a promise for resolvida com sucesso, a asserção falhará.Ele retorna o mesmo objeto
Assertions
, mas todos os matchers agora retornamPromise
, então você precisará usarawait
neles. Também funciona com asserçõeschai
.Por exemplo, se você tem uma função que falha quando você a chama, você pode usar este código para validar o motivo da rejeição:
tsimport { expect, test } from 'vitest'; async function buyApples(id) { if (!id) throw new Error('no id'); } test('buyApples lança um erro quando nenhum ID é fornecido', async () => { // toThrow retorna uma promise agora, então você PRECISA usar await await expect(buyApples()).rejects.toThrow('no id'); });
WARNING
Se a asserção não for aguardada, você terá um teste falso-positivo que sempre passará. Para garantir que as asserções sejam realmente chamadas, você pode usar
expect.assertions(number)
.
expect.assertions
Tipo:
(count: number) => void
Após o teste ter passado ou falhado, verifique se um número específico de asserções foi chamado durante um teste. Um caso de uso comum é verificar se um código assíncrono foi executado.
Por exemplo, se temos uma função que chama assincronamente dois matchers, podemos verificar se eles foram realmente chamados.
tsimport { expect, test } from 'vitest'; async function doAsync(...cbs) { await Promise.all(cbs.map((cb, index) => cb({ index }))); } test('todas as asserções são chamadas', async () => { expect.assertions(2); function callback1(data) { expect(data).toBeTruthy(); } function callback2(data) { expect(data).toBeTruthy(); } await doAsync(callback1, callback2); });
WARNING
Ao usar
assertions
com testes concorrentes assíncronos, oexpect
do Contexto de Teste local deve ser usado para garantir que o teste correto seja detectado.
expect.hasAssertions
Tipo:
() => void
Após o teste ter passado ou falhado, verifique se pelo menos uma asserção foi chamada durante um teste. Um caso de uso comum é verificar se um código assíncrono foi executado.
Por exemplo, se você tem um código que chama um callback, podemos fazer uma asserção dentro de um callback, mas o teste sempre passará se não verificarmos se uma asserção foi chamada.
tsimport { expect, test } from 'vitest'; import { db } from './db.js'; const cbs = []; function onSelect(cb) { cbs.push(cb); } // after selecting from db, we call all callbacks function select(id) { return db.select({ id }).then(data => { return Promise.all(cbs.map(cb => cb(data))); }); } test('callback foi chamado', async () => { expect.hasAssertions(); onSelect(data => { // should be called on select expect(data).toBeTruthy(); }); // if not awaited, test will fail // if you don't have expect.hasAssertions(), test will pass await select(3); });
expect.unreachable
Tipo:
(message?: string) => never
Este método é usado para afirmar que uma linha de código nunca deve ser alcançada.
Por exemplo, se quisermos testar se
build()
lança um erro devido ao recebimento de diretórios sem a pastasrc
e também lidar com cada erro separadamente, podemos fazer isso: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('build falha com "%s"', async dir => { try { await build(dir); expect.unreachable('Não deveria passar no build'); } 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: // to exhaust all error tests expect.unreachable('Todos os casos de erro devem ser tratados'); break; } } });
expect.anything
Tipo:
() => any
Este matcher assimétrico, quando usado com verificação de igualdade, sempre retornará
true
. Útil se você só quer garantir que a propriedade existe.tsimport { expect, test } from 'vitest'; test('objeto tem a chave "apples"', () => { expect({ apples: 22 }).toEqual({ apples: expect.anything() }); });
expect.any
Tipo:
(constructor: unknown) => any
Este matcher assimétrico, quando usado com uma verificação de igualdade, retornará
true
somente se o valor for uma instância de um construtor especificado. Útil se você tem um valor que é gerado dinamicamente e você só quer saber se ele existe com o tipo correto.tsimport { expect, test } from 'vitest'; import { generateId } from './generators.js'; test('"id" é um número', () => { expect({ id: generateId() }).toEqual({ id: expect.any(Number) }); });
expect.arrayContaining
Tipo:
<T>(expected: T[]) => any
Quando usado com uma verificação de igualdade, este matcher assimétrico retornará
true
se o valor for um array e contiver os itens especificados.tsimport { expect, test } from 'vitest'; test('cesta contém maçãs Fuji', () => { const basket = { varieties: ['Empire', 'Fuji', 'Gala'], count: 3, }; expect(basket).toEqual({ count: 3, varieties: expect.arrayContaining(['Fuji']), }); });
TIP
Você pode usar
expect.not
com este matcher para negar o valor esperado.
expect.objectContaining
Tipo:
(expected: any) => any
Quando usado com uma verificação de igualdade, este matcher assimétrico retornará
true
se o valor tiver uma forma semelhante.tsimport { expect, test } from 'vitest'; test('cesta tem maçãs empire', () => { const basket = { varieties: [ { name: 'Empire', count: 1, }, ], }; expect(basket).toEqual({ varieties: [expect.objectContaining({ name: 'Empire' })], }); });
TIP
Você pode usar
expect.not
com este matcher para negar o valor esperado.
expect.stringContaining
Tipo:
(expected: any) => any
Quando usado com uma verificação de igualdade, este matcher assimétrico retornará
true
se o valor for uma string e contiver uma substring especificada.tsimport { expect, test } from 'vitest'; test('o nome da variedade contém "Emp"', () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringContaining('Emp'), count: 1, }); });
TIP
Você pode usar
expect.not
com este matcher para negar o valor esperado.
expect.stringMatching
Tipo:
(expected: any) => any
Quando usado com uma verificação de igualdade, este matcher assimétrico retornará
true
se o valor for uma string e contiver uma substring especificada ou se a string corresponder a uma expressão regular.tsimport { expect, test } from 'vitest'; test('o nome da variedade termina com "re"', () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringMatching(/re$/), count: 1, }); });
TIP
Você pode usar
expect.not
com este matcher para negar o valor esperado.
expect.addSnapshotSerializer
Tipo:
(plugin: PrettyFormatPlugin) => void
Este método adiciona serializadores personalizados que são chamados ao criar um snapshot. Este é um recurso avançado - se você quiser saber mais, por favor, leia um guia sobre serializadores personalizados.
Se você estiver adicionando serializadores personalizados, você deve chamar este método dentro de
setupFiles
. Isso afetará todos os snapshots.TIP
Se você usou anteriormente o Vue CLI com Jest, você pode querer instalar jest-serializer-vue. Caso contrário, seus snapshots serão envolvidos em uma string, o que faz com que
"
seja escapado.
expect.extend
Tipo:
(matchers: MatchersObject) => void
Você pode estender os matchers padrão com os seus próprios. Esta função é usada para estender o objeto de matchers com matchers personalizados.
Quando você define matchers dessa forma, você também cria matchers assimétricos que podem ser usados como
expect.stringContaining
.tsimport { expect, test } from 'vitest'; test('matchers personalizados', () => { expect.extend({ toBeFoo: (received, expected) => { if (received !== 'foo') { return { message: () => `esperado que ${received} seja foo`, pass: false, }; } }, }); expect('foo').toBeFoo(); expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() }); });
TIP
Se você quer que seus matchers apareçam em todos os testes, você deve chamar este método dentro de
setupFiles
.Esta função é compatível com
expect.extend
do Jest, então qualquer biblioteca que a use para criar matchers personalizados funcionará com o Vitest.Se você estiver usando TypeScript, desde o Vitest 0.31.0 você pode estender a interface
Assertion
padrão em um arquivo de declaração ambient (por exemplo:vitest.d.ts
) com o código abaixo:tsinterface CustomMatchers<R = unknown> { toBeFoo(): R; } declare module 'vitest' { interface Assertion<T = any> extends CustomMatchers<T> {} interface AsymmetricMatchersContaining extends CustomMatchers {} }
WARNING
Não se esqueça de incluir o arquivo de declaração ambient em seu
tsconfig.json
.TIP
Se você quiser saber mais, confira o guia sobre como estender matchers.