[C#] Assert.Throws를 사용하여 예외 유형을 확인하려면 어떻게해야합니까?

Assert.Throws예외 유형과 실제 메시지 문구를 확인 하는 데 어떻게 사용합니까?

이 같은:

Assert.Throws<Exception>(
    ()=>user.MakeUserActive()).WithMessage("Actual exception message")

테스트하고있는 방법은 다른 메시지와 함께 동일한 유형의 여러 메시지를 throw하므로 컨텍스트에 따라 올바른 메시지가 발생하는지 테스트하는 방법이 필요합니다.



답변

Assert.Throws throw 된 예외를 반환하여 예외를 주장 할 수 있습니다.

var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));

따라서 예외가 발생하지 않거나 잘못된 유형의 예외가 발생하면 첫 번째 Assert.Throws어설 션이 실패합니다. 그러나 올바른 유형의 예외가 발생하면 변수에 저장 한 실제 예외를 주장 할 수 있습니다.

이 패턴을 사용하면 예외 메시지 이외의 다른 것을 주장 할 수 있습니다 (예 : ArgumentException및 파생 상품 의 경우) . 매개 변수 이름이 올바르다 고 주장 할 수 있습니다.

var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));

유창한 API를 사용하여 이러한 어설 션을 수행 할 수도 있습니다.

Assert.That(() => foo.Bar(null),
Throws.Exception
  .TypeOf<ArgumentNullException>()
  .With.Property("ParamName")
  .EqualTo("bar"));

또는 대안 적으로

Assert.That(
    Assert.Throws<ArgumentNullException>(() =>
        foo.Bar(null)
    .ParamName,
Is.EqualTo("bar"));

예외 메시지를 주장 할 때 약간의 팁 SetCultureAttribute은 던져진 메시지가 예상 문화권을 사용하고 있는지 확인하기 위해 테스트 방법을 장식하는 것입니다. 예외 메시지를 지역화 할 수있는 리소스로 저장하면 작동합니다.


답변

이제 ExpectedException속성을 사용할 수 있습니다 . 예 :

[Test]
[ExpectedException(typeof(InvalidOperationException),
 ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
    MethodA(null);
}


답변

Assert.That(myTestDelegate, Throws.ArgumentException
    .With.Property("Message").EqualTo("your argument is invalid."));


답변

이것은 오래된 답변과 함께 오래되었지만 관련성이 높은 질문이므로 현재 솔루션을 추가하고 있습니다.

public void Test() {
    throw new MyCustomException("You can't do that!");
}

[TestMethod]
public void ThisWillPassIfExceptionThrown()
{
    var exception = Assert.ThrowsException<MyCustomException>(
        () => Test(),
        "This should have thrown!");
    Assert.AreEqual("You can't do that!", exception.Message);
}

이것은 함께 작동 using Microsoft.VisualStudio.TestTools.UnitTesting;


답변

퍼시 스턴트의 답변을 넓히고 NUnit의 더 많은 기능을 제공하기 위해 다음과 같이 할 수 있습니다.

public bool AssertThrows<TException>(
    Action action,
    Func<TException, bool> exceptionCondition = null)
    where TException : Exception
{
    try
    {
        action();
    }
    catch (TException ex)
    {
        if (exceptionCondition != null)
        {
            return exceptionCondition(ex);
        }

        return true;
    }
    catch
    {
        return false;
    }

    return false;
}

예 :

// No exception thrown - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => {}));

// Wrong exception thrown - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new ApplicationException(); }));

// Correct exception thrown - test passes.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException(); }));

// Correct exception thrown, but wrong message - test fails.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException("ABCD"); },
        ex => ex.Message == "1234"));

// Correct exception thrown, with correct message - test passes.
Assert.IsTrue(
    AssertThrows<InvalidOperationException>(
        () => { throw new InvalidOperationException("1234"); },
        ex => ex.Message == "1234"));


답변

이 문제가 제기 된 지 오랜 시간이 걸렸지 만 최근에 같은 문제가 발생하여 MSTest에 대해이 기능을 제안합니다.

public bool AssertThrows(Action action) where T : Exception
{
try {action();}
catch(Exception exception)
{
    if (exception.GetType() == typeof(T)) return true;
}
return false;
}

용법:

Assert.IsTrue(AssertThrows<FormatException>(delegate{ newMyMethod(MyParameter); }));

더 여기 : http://phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/


답변

새로운 NUnit 패턴의 일부가 어색하기 때문에 다음과 같은 것을 사용하여 개인적으로 더 깨끗한 코드를 만듭니다.

public void AssertBusinessRuleException(TestDelegate code, string expectedMessage)
{
    var ex = Assert.Throws<BusinessRuleException>(code);
    Assert.AreEqual(ex.Message, expectedMessage);
}

public void AssertException<T>(TestDelegate code, string expectedMessage) where T:Exception
{
    var ex = Assert.Throws<T>(code);
    Assert.AreEqual(ex.Message, expectedMessage);
}

사용법은 다음과 같습니다.

AssertBusinessRuleException(() => user.MakeUserActive(), "Actual exception message");