wake-up-neo.com

Wie verwende ich Assert.Throws, um den Typ der Ausnahme zu bestätigen?

Wie verwende ich Assert.Throws, um den Typ der Ausnahme und den tatsächlichen Nachrichtenausdruck zu bestätigen.

Etwas wie das:

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

Die Methode, die ich teste, löst mehrere Nachrichten desselben Typs mit unterschiedlichen Nachrichten aus, und ich benötige eine Möglichkeit, um zu testen, ob die richtige Nachricht abhängig vom Kontext ausgelöst wird.

219
epitka

Assert.Throws gibt die ausgelöste Ausnahme zurück, mit der Sie die Ausnahme bestätigen können.

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

Wenn also keine Ausnahme oder eine Ausnahme des falschen Typs ausgelöst wird, wird die erste Assert.Throws Assertion wird fehlschlagen. Wenn jedoch eine Ausnahme vom richtigen Typ ausgelöst wird, können Sie jetzt die tatsächliche Ausnahme bestätigen, die Sie in der Variablen gespeichert haben.

Durch Verwenden dieses Musters können Sie andere Dinge als die Ausnahmemeldung bestätigen, z. Im Fall von ArgumentException und Derivaten können Sie davon ausgehen, dass der Parametername korrekt ist:

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

Sie können die fließende API auch für die folgenden Asserts verwenden:

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

Ein kleiner Tipp, wenn Sie Ausnahmemeldungen geltend machen, ist, die Testmethode mit dem SetCultureAttribute zu dekorieren, um sicherzustellen, dass die ausgelöste Nachricht die erwartete Kultur verwendet. Dies kommt zum Tragen, wenn Sie Ihre Ausnahmemeldungen als Ressourcen speichern, um die Lokalisierung zu ermöglichen.

396
Patrik Hägne

Sie können jetzt die Attribute ExpectedException verwenden, z.

[Test]
[ExpectedException(typeof(InvalidOperationException), 
 ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
    MethodA(null);
}
24
Jackson Pope
Assert.That(myTestDelegate, Throws.ArgumentException
    .With.Property("Message").EqualTo("your argument is invalid."));
13
Jordan Morris

Dies ist eine alte, aber relevante Frage mit veralteten Antworten, daher füge ich die aktuelle Lösung hinzu:

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);
}

Dies funktioniert mit using Microsoft.VisualStudio.TestTools.UnitTesting;

3
Tvde1

So erweitern Sie die Antwort von persistent und stellen mehr Funktionen von NUnit zur Verfügung:

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; 
}

Beispiele:

// 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"));
3
fre0n

Es ist lange her, dass dieses Problem angesprochen wurde, aber ich bin kürzlich auf dasselbe gestoßen und habe diese Funktion für MSTest vorgeschlagen:

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

verwendung:

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

Mehr hier: http://phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/

2
persistent

Da mich die Ausführlichkeit einiger der neuen NUnit-Muster stört, benutze ich so etwas, um Code zu erstellen, der für mich persönlich sauberer ist:

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);
}

Die Verwendung ist dann:

AssertBusinessRuleException(() => service.Create(content), "Name already exists");
1
Savage