shouldly / shouldly

Should testing for .NET—the way assertions should be!

Home Page:https://docs.shouldly.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

No ShouldThrow<T> overload for Func returning primitive.

mgraf1 opened this issue · comments

Version: 2.4.1

Consider the following code:

void Main()
{
    var func1 = () => MethodReturningObject();
    func1.ShouldThrow<ArgumentException>();
    
    var func2 = () => MethodReturningNullableInt();
    func2.ShouldThrow<ArgumentException>(); // Does not compile.
    
    var func3 = () => MethodReturningInt();
    func3.ShouldThrow<ArgumentException>(); // Does not compile.
}

public object MethodReturningObject()
{
    return 1;
}

public int MethodReturningNullableInt()
{
    return 1;
}

public int MethodReturningInt()
{
    return 1;
}

There should be an overload of ShouldThrow<TException> which works for Func where T is a struct. It's worth noting that ShouldNotThrow compiles just fine.

I would be willing to try to submit a PR if the maintainers agree that this sort of functionality would be valuable.

I've spent some time playing with the code. The main issue is that current overloads of ShouldThrow<T> take Func<object?> which does not work for things like Func<int>.

I see a few options

Instead of adding an overload for ShouldThrow<T>, the non-generic method ShouldThrow which takes an exception type as a parameter could be changed to take Func instead of Func<object?>. This would allow it to work in all cases.

The same approach cannot be done for ShouldThrow<T>. An overload with an additional generic type parameter could be added. The downside though is that it's more awkward to use. It would look like

var func1 = () => MethodReturningInt();
func1.ShouldThrow<ArgumentException, int>();

Which feels weird to me.

Another option would be to change ShouldThrow<T> to a signature like this which uses Delegate instead of Func<object?>.

public static TException ShouldThrow<TException>(this Delegate actual, string? customMessage = null)
    where TException : Exception 

This works for pretty much any Action or Func parameter. Alternatively, it could be added as a separate overload. There may be additional downsides to using Delegate, though that I'm not aware of.