Jasmine에서 오류가 발생할 것으로 예상되는 테스트를 작성하는 방법은 무엇입니까?


490

오류가 예상되는 Jasmine Test Framework에 대한 테스트를 작성하려고합니다 . 현재 GitHubJasmine Node.js 통합을 사용하고 있습니다 .

내 노드 모듈에는 다음 코드가 있습니다.

throw new Error("Parsing is not possible");

이제이 오류가 예상되는 테스트를 작성하려고합니다.

describe('my suite...', function() {
    [..]
    it('should not parse foo', function() {
    [..]
        expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));
    });
});

나는 또한 Error()다른 변형을 시도했지만 어떻게 작동시키는 지 알 수 없습니다.


4
익명 함수를 사용하지 않고, 함수에 대한 인수가 테스트되고 전달하려면 시도 Function.bind: stackoverflow.com/a/13233194/294855
Danyal Aytekin

답변:


802

함수를 expect(...)호출에 전달해야합니다 . 여기있는 코드 :

// incorrect:
expect(parser.parse(raw)).toThrow(new Error("Parsing is not possible"));

실제로하려고 전화 parser.parse(raw) 로 결과를 전달하는 시도 expect(...),

대신 익명 함수를 사용해보십시오.

expect( function(){ parser.parse(raw); } ).toThrow(new Error("Parsing is not possible"));

28
인수도 전달할 필요가없는 경우 함수를 전달하여 다음을 기대할 수도 있습니다.expect(parser.parse).toThrow(...)
SubmittedDenied

60
유용한 팁 : 간단히 전화하면 expect(blah).toThrow()됩니다. 인수가 없다는 것은 그것이 던져지는 것을 확인하는 것을 의미합니다. 일치하는 문자열이 없습니다. 또한보십시오 : stackoverflow.com/a/9525172/1804678
Jess

1
제 생각에는 익명 함수로 래핑 할 때 테스트의 의도가 더 분명합니다. 또한 예를 들어 매개 변수를 대상 함수에 전달하여 던져야하는 경우 모든 테스트에서 일관성을 유지합니다.
Beez

10
@SubmittedDenied : 이것은 일반적으로 작동하지 않습니다! 을 parser.parse사용 this하는 경우 컨텍스트없이 전달하면 예기치 않은 결과가 발생합니다. 당신은 통과 할 수 parser.parse.bind(parser)있지만, 솔직히 ... 익명 함수는 더 우아 할 것입니다.
mhelvens

2
@LanceKind necro에 죄송하지만 함수를 전달 해야하는 이유는 예상에 전달되기 전에 값이 평가되고 예외가 발생하기 때문입니다.
1g 위도

68

당신은 사용하고 있습니다 :

expect(fn).toThrow(e)

그러나 함수 주석을 살펴보면 문자열이 예상됩니다.

294 /**
295  * Matcher that checks that the expected exception was thrown by the actual.
296  *
297  * @param {String} expected
298  */
299 jasmine.Matchers.prototype.toThrow = function(expected) {

람다-익명 함수를 사용하여 다음과 같이 작성해야한다고 가정합니다.

expect(function() { parser.parse(raw); } ).toThrow("Parsing is not possible");

이것은 다음 예에서 확인됩니다.

expect(function () {throw new Error("Parsing is not possible")}).toThrow("Parsing is not possible");

Douglas Crockford는 "throw new Error ()"(프로토 타이핑 방식)를 사용하는 대신이 접근 방식을 강력히 권장합니다.

throw {
   name: "Error",
   message: "Parsing is not possible"
}

3
실제로 toThrow 코드를 보면 예외 객체 또는 문자열을 행복하게 취할 수 있습니다. 예를 들어 예상되는 호출을 확인하십시오.
피트 호지 슨

1
메시지 속성이없는 문자열의 부작용으로 문자열을 허용하는 이음새
mpapis

1
고마워요. 그의 대답은 내가하는 것이 나에게 더 명확하게 만들어 beacuse 나는 아직도, 피트의 대답을 받아 가지고 람다를 사용 할 수 있습니다. 여전히 +1 :-) 감사합니다!
echox

16
오류가 아닌 객체를 던지면 (아래의 예와 같이) 브라우저를 지원하는 브라우저에서 스택 추적을 얻지 못합니다.
kybernetikos

2
@kybernetikos 놀랍게도, 전적으로 사실이 아닙니다. Error( jsfiddle.net/k1mxey8j ) 를 던지지 않으면 Chrome 콘솔에 여전히 스택 추적이 인쇄됩니다 . 그러나 던져진 객체에는 .stack속성 이 없으므로 자동 오류보고 를 설정하려는 경우 중요 할 수 있습니다 .
Mark Amery

24

유일한 목적을 가진 익명의 기능을 만드는 것보다 더 우아한 해결책은 es5의 bind기능 을 사용하는 것 입니다. 바인드 함수는 호출 될 때 this키워드가 제공된 값으로 설정되고 새 함수가 호출 될 때 지정된 인수 시퀀스가 ​​앞에 오는 새 함수를 작성합니다.

대신에:

expect(function () { parser.parse(raw, config); } ).toThrow("Parsing is not possible");

치다:

expect(parser.parse.bind(parser, raw, config)).toThrow("Parsing is not possible");

바인드 구문을 사용하면 다른 this값으로 함수를 테스트 할 수 있으며 내 의견으로는 테스트를 더 읽기 쉽게 만듭니다. 참조 : https://stackoverflow.com/a/13233194/1248889


23

Jasmine의 toThrow 매처를 다음으로 바꾸면 예외의 name 속성 또는 message 속성과 일치시킬 수 있습니다. 나에게 이것은 다음을 수행 할 수 있기 때문에 테스트를보다 쉽게 ​​작성하고 덜 취성있게 만듭니다.

throw {
   name: "NoActionProvided",
   message: "Please specify an 'action' property when configuring the action map."
}

그런 다음 다음을 사용하여 테스트하십시오.

expect (function () {
   .. do something
}).toThrow ("NoActionProvided");

이것은 중요한 예외가 예상되는 유형의 예외를 던질 때 테스트를 중단하지 않고 나중에 예외 메시지를 조정할 수있게합니다.

이것은 이것을 허용하는 toThrow를 대체합니다.

jasmine.Matchers.prototype.toThrow = function(expected) {
  var result = false;
  var exception;
  if (typeof this.actual != 'function') {
    throw new Error('Actual is not a function');
  }
  try {
    this.actual();
  } catch (e) {
    exception = e;
  }
  if (exception) {
      result = (expected === jasmine.undefined || this.env.equals_(exception.message || exception, expected.message || expected) || this.env.equals_(exception.name, expected));
  }

  var not = this.isNot ? "not " : "";

  this.message = function() {
    if (exception && (expected === jasmine.undefined || !this.env.equals_(exception.message || exception, expected.message || expected))) {
      return ["Expected function " + not + "to throw", expected ? expected.name || expected.message || expected : " an exception", ", but it threw", exception.name || exception.message || exception].join(' ');
    } else {
      return "Expected function to throw an exception.";
    }
  };

  return result;
};

4
좋은 접근 방법이지만 {name : '...', message : '...'}은 JavaScript에서 적절한 Error 객체입니까?
Marc

1
좋은 의견 @Marc. 당신이 맞습니다, 이름 속성은 표준이 아닙니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 그러나 그렇게 잘못 되었습니까?
Jess

4
@ 제이크! 나는 더 좋은 길을 찾았다 !!!! 간단하게 전화를 걸 수 있습니다 expect(blah).toThrow(). 인수가 없다는 것은 그것이 던져지는 것을 확인하는 것을 의미합니다. 일치하는 문자열이 없습니다. 또한보십시오 : stackoverflow.com/a/9525172/1804678
Jess

5
고마워 Jess-그건 사실이지만 TypeError와 같은 다른 오류가 발생할 수 있으며 테스트가 잘못 통과하여 실제 버그가 숨겨집니다.
Jake

4
이제 toThrow ()의 인수로 RegEx를 사용할 수도 있습니다.
Tony O'Hagan

21

앞에서 언급했듯이 함수는 toThrow테스트에서 설명하는 함수이므로 전달해야합니다 . "이 함수는 x를 던질 것으로 예상합니다."

expect(() => parser.parse(raw))
  .toThrow(new Error('Parsing is not possible'));

사용하는 경우 재스민-매처 (Matchers)을 가 상황에 맞게 때 당신은 또한 다음 중 하나를 사용할 수 있습니다;

// I just want to know that an error was
// thrown and nothing more about it
expect(() => parser.parse(raw))
  .toThrowAnyError();

또는

// I just want to know that an error of 
// a given type was thrown and nothing more
expect(() => parser.parse(raw))
  .toThrowErrorOfType(TypeError);

3
그것은이다 expect(foo).toThrowError(TypeError);재스민 2.5 : jasmine.github.io/2.5/introduction
베니 노이게 바우어에게

9

나는 그것이 더 많은 코드라는 것을 알고 있지만 당신은 또한 할 수 있습니다 :

try
   do something
   @fail Error("should send a Exception")
 catch e
   expect(e.name).toBe "BLA_ERROR"
   expect(e.message).toBe 'Message'

"자체 문서화"측면을 좋아하는 경향이 있습니다. 오류 상태를 단위로 테스트하고 있음을 분명히 보여줍니다.
JRulle

6

커피 스크립트 애호가

expect( => someMethodCall(arg1, arg2)).toThrow()

3

여전히이 문제에 직면하고있는 사람은 저에게 게시 된 솔루션이 작동하지 않고이 오류가 계속 발생합니다. Error: Expected function to throw an exception. 나중에 오류를 던질 것으로 예상되는 기능이 비동기 기능이며 거부되고 오류가 발생하면 코드에서 수행 한 작업입니다.

throw new Error('REQUEST ID NOT FOUND');

그게 내가 테스트에서 한 일이며 효과가있었습니다.

it('Test should throw error if request not found', willResolve(() => {
         const promise = service.getRequestStatus('request-id');
                return expectToReject(promise).then((err) => {
                    expect(err.message).toEqual('REQUEST NOT FOUND');
                });
            }));

고마워 매우 혼란 스러웠지만 귀하의 의견은 완벽합니다. 새로운 expectAsync jasmine.github.io/api/3.3/async-matchers.html
Benjamin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.