Jest'te atılan istisna türü nasıl test edilir


161

İşlev tarafından atılan istisna türünü test etmem gereken bazı kodlarla çalışıyorum (TypeError, ReferenceError vb.).

Şu anki test çerçevem ​​AVA ve burada olduğu gibi ikinci bir argüman t.throwsyöntemi olarak test edebilirim :

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  t.is(error.message, 'UNKNOWN ERROR');
});

Testlerimi Jest'e yeniden yazmaya başladım ve bunu nasıl kolayca yapacağımı bulamadım. Hatta mümkün mü?

Yanıtlar:


225

Jest'te, bir işlevi bekleme (işlev) .toThrow (boş veya hata türü) içine geçirmeniz gerekir.

Misal:

test("Test description", () => {
  const t = () => {
    throw new TypeError();
  };
  expect(t).toThrow(TypeError);
});

Varolan bir işlevi bir dizi bağımsız değişkenle atıp atmadığını test etmeniz gerekiyorsa, onu wait () 'deki anonim bir işlevin içine sarmalısınız.

Misal:

test("Test description", () => {
  expect(() => {http.get(yourUrl, yourCallbackFn)}).toThrow(TypeError);
});

79

Biraz tuhaf, ama işe yarıyor ve imho iyi okunabilir:

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
  try {
      throwError();
      // Fail test if above expression doesn't throw anything.
      expect(true).toBe(false);
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

Catchblok istisnanızı yakalarsa, yükselttiğinizde test edebilirsiniz Error. expect(true).toBe(false);Beklendiği Errortakdirde testin başarısız olması için garip bir şey atılmayacak. Aksi takdirde, bu çizgiye asla ulaşılamaz ( Erroronlardan önce yükseltilmelidir).

DÜZENLEME: @Kenny Body, kullanırsanız kod kalitesini artıran daha iyi bir çözüm önerir expect.assertions()

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', () => {
  expect.assertions(1);
  try {
      throwError();
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

Daha fazla açıklamayla orijinal yanıta bakın: Jest'te atılan istisna türü nasıl test edilir


18
Jest halihazırda istisnaları kontrol etmek için wait.toThrow () yöntemine sahipken, istisnaları test etmenin çok ayrıntılı bir yoludur: jestjs.io/docs/en/expect.html#tothrowerror
gomisha

4
Evet, ancak yalnızca türü test eder, mesajı veya diğer içeriği test etmez ve soru tiple değil, test mesajıyla ilgiliydi.
bodolsog

2
Hah. Kodumun fırlatılan hatanın bir değerini test etmesi gerektiği için örneğe ihtiyacım olduğu için gerçekten buna benziyor. Hatalı beklentiyi expect('here').not.toBe('here');sadece eğlence olsun diye
Valery

4
@ Valery veya: expect('to be').not.toBe('to be')Shakespeare tarzında.
Michiel van der Blonk

2
en küçümsenen cevap!
Edwin Ikechukwu Okonkwo

42

Biraz daha özlü bir versiyon kullanıyorum:

expect(() => {
  //code block that should throw error
}).toThrow(TypeError) //or .toThrow('expectedErrorMessage')

2
Kısa ve kesin.
flapjack

33

Jest'e (sınırlı da olsa) maruz kalmamdan, expect().toThrow()SADECE belirli bir türden bir hatanın atıldığını test etmek istiyorsanız bunun uygun olduğunu buldum :

expect(() => functionUnderTest()).toThrow(TypeError);

VEYA belirli bir mesajla bir hata atılır:

expect(() => functionUnderTest()).toThrow('Something bad happened!');

İkisini de yapmaya çalışırsanız, yanlış bir pozitif alırsınız. Örneğin, kodunuz atarsa RangeError('Something bad happened!'), bu test geçecektir:

expect(() => functionUnderTest()).toThrow(new TypeError('Something bad happened!'));

Bir dene / yakala kullanmayı öneren bodolsog tarafından verilen cevap yakındır, ancak yakalamadaki beklenen iddiaların tutturulmasını sağlamak için doğru olmasını beklemek yerine expect.assertions(2), testinizin başında 2beklenen iddiaların sayısının olduğu yerde kullanabilirsiniz . . Bunun testin amacını daha doğru tanımladığını düşünüyorum.

Bir hatanın türünü VE mesajını test etmenin tam örneği:

describe('functionUnderTest', () => {
    it('should throw a specific type of error.', () => {
        expect.assertions(2);

        try {
            functionUnderTest();
        } catch (error) {
            expect(error).toBeInstanceOf(TypeError);
            expect(error).toHaveProperty('message', 'Something bad happened!');
        }
    }); 
});

Bir functionUnderTest()hata ATMAZSA, iddialar tutulur, ancak expect.assertions(2)başarısız olur ve test başarısız olur.


D'oh. Her zaman Jest'in birden fazla iddia beklediğini unutuyorum (muhtemelen bunu kişisel olarak en sezgisel bulmuyorum, ama kesinlikle bu gibi durumlarda işe yarıyor!) Şerefe!
kpollock

Bu benim için gayet iyi çalıştı. Bu kullanılmalıdır.
Ankit Tanna

expect.hasAssertions()Testin dışında herhangi bir iddia yoksa daha iyi bir alternatif olabilir catch, çünkü iddiaları ekler / kaldırırsanız numarayı güncellemeniz gerekmez.
André Sassi

12

Ben kendim denemedim ama Jest'in iddiasını kullanmak için kullanmanızı öneririm . Öyleyse sanırım örneğiniz şuna benzer:

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  expect(t).toThrowError('UNKNOWN ERROR');
  //or
  expect(t).toThrowError(TypeError);
});

Yine, test etmedim ama işe yaraması gerektiğini düşünüyorum.


8

Jest, toThrow(error)çağrıldığında bir işlevin attığını test etmek için bir yönteme sahiptir .

Öyleyse, senin durumunda şöyle demelisin:

expect(t).toThrowError(TypeError);

Dokümanlar


1
Durum için işe yaramaz: jest.spyOn(service, 'create').mockImplementation(() => { throw new Error(); });alay edilen yöntem createdeğilse async.
Sergey

7

Modern şaka, reddedilen değer üzerinde daha fazla kontrol yapmanızı sağlar. Örneğin:

const request = Promise.reject({statusCode: 404})
await expect(request).rejects.toMatchObject({ statusCode: 500 });

hata ile başarısız olur

Error: expect(received).rejects.toMatchObject(expected)

- Expected
+ Received

  Object {
-   "statusCode": 500,
+   "statusCode": 404,
  }

6

Dokümantasyon Bu nasıl yapılacağına ilişkin açıktır. Diyelim ki iki parametre alan bir fonksiyonum var ve bunlardan biri olursa hata verecek null.

function concatStr(str1, str2) {
  const isStr1 = str1 === null
  const isStr2 = str2 === null
  if(isStr1 || isStr2) {
    throw "Parameters can't be null"
  }
  ... // continue your code

Senin testin

describe("errors", () => {
  it("should error if any is null", () => {
    // notice that the expect has a function that returns the function under test
    expect(() => concatStr(null, "test")).toThrow()
  })
})

5

S ile çalışıyorsanız Promise:

await expect(Promise.reject(new HttpException('Error message', 402)))
  .rejects.toThrowError(HttpException);

Bu çok yararlı, zamanımı kurtardığın için teşekkürler !!
Aditya Kresna Permana

3

Test-utils kitaplığımız için kullanışlı bir yöntem yazdım

/**
 *  Utility method to test for a specific error class and message in Jest
 * @param {fn, expectedErrorClass, expectedErrorMessage }
 * @example   failTest({
      fn: () => {
        return new MyObject({
          param: 'stuff'
        })
      },
      expectedErrorClass: MyError,
      expectedErrorMessage: 'stuff not yet implemented'
    })
 */
  failTest: ({ fn, expectedErrorClass, expectedErrorMessage }) => {
    try {
      fn()
      expect(true).toBeFalsy()
    } catch (err) {
      let isExpectedErr = err instanceof expectedErrorClass
      expect(isExpectedErr).toBeTruthy()
      expect(err.message).toBe(expectedErrorMessage)
    }
  }

Aynı şey Jestlerin kendi özellikleri kullanılarak da yapılabilir. Bunun nasıl yapılacağına dair cevabımı görün - stackoverflow.com/a/58103698/3361387
Kenny Body

3

Peter Danis'in gönderisine ek olarak, çözümünün "bir işlevi beklenen (işlev) .toThrow (boş veya hata türü) içine [geçirme]" kısmını vurgulamak istedim.

Jest'te, bir hatanın atılması gereken bir durumu test ettiğinizde, test edilen işlevin beklenen () sarmalanması dahilinde, çalışması için ek bir ok işlevi sarma katmanı sağlamanız gerekir. yani

Yanlış (ancak çoğu insanın mantıklı yaklaşımı):

expect(functionUnderTesting();).toThrow(ErrorTypeOrErrorMessage);

Sağ:

expect(() => { functionUnderTesting(); }).toThrow(ErrorTypeOrErrorMessage);

Bu çok garip ama testin başarılı bir şekilde yürütülmesini sağlamalı.


1

Deneyin
expect(t).rejects.toThrow()


4
Neden try? denemek yok - ama cevap var. Cevap buysa lütfen daha fazla ayrıntı verin. mevcut cevaba ne ekliyorsunuz?
dWinder

7
Sanırım @ Razim, çözümü denemeniz gerektiğini söylüyordu, deneme yakalama kullanmamalısınız.
Tom
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.