28

Normally you test, if an exception gets thrown in a certain method, as follows. I use FluentAssertions:

[Fact]
public void Exception_gets_thrown()
{
    // Arrange
    var foo = new Foo("validArgument");

    // Act/Assert
    foo.Invoking(f => f.Bar(null))            // null is an invalid argument
       .ShouldThrow<ArgumentNullException>();
}

But how to test, if an exception gets thrown in the constructor? I just did it like this, but is there maybe a more appropriate way via FluentAssertions?

[Fact]
public void Constructor_throws_Exception()
{
    // Arrange
    Action a = () => new Foo(null);         // null is an invalid argument

    // Act/Assert
    a.ShouldThrow<ArgumentNullException>();
}
Michael Schnerring
  • 3,584
  • 4
  • 23
  • 53

3 Answers3

26

That's exactly how you're supposed to test for exceptions and that's what ShouldThrow<T>() and ShouldNotThrow<T>() were designed for in the first place. In fact, the Invoking() approach might be marked as obsolete in the next big version (2.0.0).

Ruben Bartelink
  • 59,778
  • 26
  • 187
  • 249
Dennis Doomen
  • 8,368
  • 1
  • 32
  • 44
  • But is it the right way to test, if an exception gets thrown in the constructor? Via this action? – Michael Schnerring Jun 06 '12 at 10:14
  • 1
    Shame about obsoleting the Invoking() approach. I find it far easier to read than the Action mechanism displayed in the second test above. Invoking keeps everything nicely together so the intent is obvious. – Jack Hughes Jul 11 '12 at 13:57
  • @ebeen I usually just use the [ExpectedException(typeof(ArgumentNullException))] when testing exceptions being thrown from the constructor. Given that there is only one line in the test, the exception can only be thrown from there. – Jack Hughes Jul 11 '12 at 14:00
  • 3
    @JackHughes The reason why we introduced the Invoking() and ShouldThrow() variants is to get rid of those [ExpectedException] attributes. The Unit Test project for Metro apps doesn't even support that attribute anymore. – Dennis Doomen Jul 11 '12 at 14:05
  • Not a huge fan of [ExpectedException] either... I just prefer it to using the Action syntax from FA in that very specific case. I use FA everywhere else :) – Jack Hughes Jul 11 '12 at 14:49
  • 2
    The Invoking construct is a nice API IMHO BTW :) – Jack Hughes Jul 11 '12 at 14:50
  • 5
    @DennisDoomen - That's Customer Service!! :) – Sam Aug 14 '13 at 04:38
  • 2
    We're about to release 2.1, and it's still in ;-) – Dennis Doomen Aug 15 '13 at 05:55
4

I added a helper method like the below for use when testing constructors:

static Action Constructor<T>(Func<T> func)
{
    return () => func();
}

which I then use like this:

Constructor(() => new Foo("bar", null))
.ShouldThrow<ArgumentNullException>()
.And
.ParamName
.Should()
.Be("baz");

I know it's a matter of personal taste, but I find this a bit cleaner than needing to declare and assign a delegate first.

This would make the code in the original question look like this:

[Fact]
public void Constructor_throws_Exception()
{    
    // Act/Assert
    Constructor(() => new Foo(null)).ShouldThrow<ArgumentNullException>();
}
Martin Costello
  • 9,672
  • 5
  • 60
  • 72
4

There's a built-in.

FluentActions.Invoking(() => new Foo(null)).ShouldThrow<ArgumentNullException>();
Jevon Kendon
  • 545
  • 4
  • 13