Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MOQ - verify exception was thrown

I working with MOQ framework for my testing. I have a scenario in which I expect a fault exception to be thrown. How can I verify it was thrown?

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

Thanks in advance.

like image 304
Gal Ziv Avatar asked Apr 17 '13 06:04

Gal Ziv


5 Answers

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

like image 160
treze Avatar answered Oct 06 '22 17:10

treze


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.

like image 31
AlanT Avatar answered Oct 06 '22 15:10

AlanT


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.

like image 29
DaveN59 Avatar answered Oct 06 '22 15:10

DaveN59


Please read this Introduction to Moq. Here is the way to setup InvalidOperationException throwing when DoSomething method is invoked:

mock.Setup(foo => foo.DoSomething()).Throws<InvalidOperationException>();

Then simply verify if method was called. If it was called, then exception was raised

mock.Verify(foo => foo.DoSomething());
like image 33
Sergey Berezovskiy Avatar answered Oct 06 '22 16:10

Sergey Berezovskiy


You can test that an Exception is thrown using NUnit Asserts:

Assert.That(() => testObject.methodToTest(), Throws.TypeOf<FaultException>());
like image 42
g t Avatar answered Oct 06 '22 16:10

g t