Jak używać Assert.Rzuty, aby potwierdzić typ wyjątku?

Jak używać Assert.Throws do określenia typu wyjątku i rzeczywistego brzmienia komunikatu.

Coś takiego:

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

Metoda, którą testuję rzuca wiele wiadomości tego samego typu, z różnymi wiadomościami i potrzebuję sposobu, aby sprawdzić, czy poprawna wiadomość jest wyrzucana w zależności od kontekstu.

Author: Liam, 2009-10-22

6 answers

Assert.Throws zwraca wyrzucony wyjątek, który pozwala na stwierdzenie wyjątku.

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

Więc jeśli żaden wyjątek nie zostanie wyrzucony lub wyjątek niewłaściwego typu zostanie wyrzucony, pierwsze twierdzenie Assert.Throws zakończy się niepowodzeniem. Jeśli jednak zostanie wyrzucony wyjątek właściwego typu, możesz teraz stwierdzić rzeczywisty wyjątek zapisany w zmiennej.

Za pomocą tego wzorca można stwierdzić inne rzeczy niż komunikat wyjątku, np. w przypadku ArgumentException i pochodnych, można upewnij się, że nazwa parametru jest poprawna:

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

Możesz również użyć płynnego API do wykonywania tych twierdzeń:

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

Małą wskazówką podczas sprawdzania wiadomości wyjątków jest udekorowanie metody testowej SetCultureAttribute, aby upewnić się, że rzucona wiadomość korzysta z oczekiwanej Kultury. To wchodzi w grę, jeśli przechowujesz wiadomości WYJĄTKÓW jako zasoby, aby umożliwić lokalizację.

 335
Author: Patrik Hägne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-03 09:58:29

Możesz teraz używać atrybutów ExpectedException, np.

[Test]
[ExpectedException(typeof(InvalidOperationException), 
 ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
    MethodA(null);
}
 22
Author: Jackson Pope,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-03 09:58:28
Assert.That(myTestDelegate, Throws.ArgumentException
    .With.Property("Message").EqualTo("your argument is invalid."));
 10
Author: Jordan Morris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 02:33:59

Aby rozszerzyć odpowiedź persistent i zapewnić więcej funkcjonalności NUnit, możesz to zrobić:

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

Przykłady:

// 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
Author: fre0n,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-08 20:41:00

Dawno nie poruszano tego problemu, zdaję sobie sprawę, ale ostatnio natknąłem się na to samo i zaproponowałem tę funkcję dla MSTest:

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

Użycie:

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

Więcej tutaj: http://phejndorf.wordpress.com/2011/02/21/assert-that-a-particular-exception-has-occured/

 2
Author: persistent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-02 07:28:46

Ponieważ niepokoi mnie słowność niektórych nowych szablonów NUnit, używam czegoś takiego do tworzenia kodu, który jest czystszy dla mnie osobiście:

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

Użycie jest wtedy:

AssertBusinessRuleException(() => service.Create(content), "Name already exists");
 1
Author: Savage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-09 15:24:07