MOQ - verify exception was thrown

Solution 1:

If you want to verify an exception was thrown (by your own code) then Moq is not your tool of choice for that. Simply use one of the unit test frameworks available.

Xunit/NUnit:

Assert.Throws<SomeException>(() => foo.Bar());

Fluent Assertions:

Action act = () => foo.Bar();
act.Should().Throw<SomeException>();
               

https://fluentassertions.com/introduction

http://www.nunit.org/index.php?p=exceptionAsserts&r=2.6.2

Solution 2:

I may be mis-reading your intent, but as far as I can see there is no need to do anything to a mock in order to test that the exception has been thrown.

It looks like you have a class with a method Foo that takes a string - lets call this InnerClass

public class InnerClass {
    public virtual void Foo(string str) {
         // do something with the string
    }
}

and a class which contains an InnerClass as a property (someProperty) which has a member Koko that takes a List<string> as a parameter

public class OuterClass {

    private readonly InnerClass someProperty;

    public OuterClass(InnerClass someProperty) {
        this.someProperty = someProperty;
    }

    public void Koko(List<string> list) {
         foreach (var str in list) {
              if (str != null)
                   someProperty.Foo(str);
              else
                   throw new FormatException();
          }
    } 
}

NOTE: I cannot get List<string?> to compile - tells me that the underlying type (string) must be non-nullable. AFAIK, one only needs to make value types nullable, reference types are implicitly nullable.

It looks like you want to test that if you pass in a list of strings where any of them are null that a FormatException is thrown.

If so, then the only reason for a MOQ is to release us from worrying about the InnerClass functionality. Foo is a method, so, unless we are using strict mocks, we can just create an InnerClass mock with no other setup.

There is an attribute [ExpectedException] with which we can tag our test to verify that the exception has been thrown.

[TestMethod]
[ExpectedException(typeof(FormatException))]
public void ExceptionThrown() {

    var list = new List<string>() {
        "Abel",
        "Baker",
        null,
        "Charlie"
    };

    var outer = new OuterClass(new Mock<InnerClass>().Object);
    outer.Koko(list);

}

This test will pass if a FormatException is thrown and fail if it is not.

Solution 3:

Reading through these answers I realized there is yet another way to do this using NUnit. The following gets the exception text from an exception and verifies the error message text.

var ex = Assert.Throws<SomeException>(() => foo.Bar());
Assert.That(ex.Message, Is.EqualTo("Expected exception text");

And I couldn't get the decoration / attribute syntax to work (AlanT's answer above) using the latest version of NUnit -- not sure why, but it complained no matter what I tried to do.