How do I use Assert.Throws to assert the type of the exception?

后端 未结 7 1507
你的背包
你的背包 2020-12-02 04:51

How do I use Assert.Throws to assert the type of the exception and the actual message wording?

Something like this:

Assert.Throws

        
相关标签:
7条回答
  • 2020-12-02 05:24

    You can now use the ExpectedException attributes, e.g.

    [Test]
    [ExpectedException(typeof(InvalidOperationException), 
     ExpectedMessage="You can't do that!"]
    public void MethodA_WithNull_ThrowsInvalidOperationException()
    {
        MethodA(null);
    }
    
    0 讨论(0)
  • 2020-12-02 05:33

    Assert.Throws returns the exception that's thrown which lets you assert on the exception.

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

    So if no exception is thrown, or an exception of the wrong type is thrown, the first Assert.Throws assertion will fail. However if an exception of the correct type is thrown then you can now assert on the actual exception that you've saved in the variable.

    By using this pattern you can assert on other things than the exception message, e.g. in the case of ArgumentException and derivatives, you can assert that the parameter name is correct:

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

    You can also use the fluent API for doing these asserts:

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

    or alternatively

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

    A little tip when asserting on exception messages is to decorate the test method with the SetCultureAttribute to make sure that the thrown message is using the expected culture. This comes into play if you store your exception messages as resources to allow for localization.

    0 讨论(0)
  • 2020-12-02 05:39
    Assert.That(myTestDelegate, Throws.ArgumentException
        .With.Property("Message").EqualTo("your argument is invalid."));
    
    0 讨论(0)
  • 2020-12-02 05:42

    Since I'm disturbed by the verbosity of some of the new NUnit patterns, I use something like this to create code that is cleaner for me personally:

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

    The usage is then:

    AssertBusinessRuleException(() => user.MakeUserActive(), "Actual exception message");
    
    0 讨论(0)
  • 2020-12-02 05:46

    A solution that actually works:

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

    This works with using Microsoft.VisualStudio.TestTools.UnitTesting;.

    0 讨论(0)
  • 2020-12-02 05:48

    I recently ran into the same thing, and suggest this function for MSTest:

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

    Usage:

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

    There is more in Assert that a particular exception has occured (Assert.Throws in MSTest).

    0 讨论(0)
提交回复
热议问题