Fluentassertions: AllBeAssignableTo behaving not like foreach BeAssignableTo

Created on 5 Mar 2019  路  4Comments  路  Source: fluentassertions/fluentassertions

I use some reflection to test that all my controllers implement my BaseController.
When I test with AllBeAssignableTo it fails:

var myBaseControllerType = typeof(BaseController);
var controllers = myBaseControllerType.Assembly.Types().Where(x => x.Implements(typeof(ControllerBase)) && x != myBaseControllerType);
controllers.Should().AllBeAssignableTo<BaseController>();

Expected type to be "MyProject.Controllers.BaseController", but found "[System.RuntimeType, System.RuntimeType, System.RuntimeType, System.RuntimeType]".

However, when I use foreach, it works like a charm

var myBaseControllerType = typeof(BaseController);
var controllers = myBaseControllerType.Assembly.Types().Where(x => x.Implements(typeof(ControllerBase)) && x != myBaseControllerType);
foreach (var controller in controllers)
{
    controller.Should().BeAssignableTo<BaseController>();
}

To me this is very unexpected. Can someone explain it? Or is it a bug? Not sure.

BR Matthias

enhancement

Most helpful comment

Fair enough. We could just fix it internally. If the collection is of type IEnumerable<RuntimeTypeInfo or IEnumerable<Type>, it does what you expext it to do.

All 4 comments

There are two overloads of BeAssignableTo

  • ReferenceTypeAssertions.BeAssignableTo<T>() checks if the type of the subject is assignable to T
  • TypeAssertions.BeAssignableTo<T>() checks if the subject, which is a Type is assignable to T

Your second example will use TypeAssertions.BeAssignableTo(), which is why it works as expected.

AllBeAssignableTo has a single overload CollectionAssertions.AllBeAssignableTo<T>()
which can be seen as a collection edition of ReferenceTypeAssertions.BeAssignableTo<T>().

In your case:
Instead of checking { typeof(Controller1), typeof(Controller2) } it will check their types, and as typeof(Controller1).GetType() is System.RuntimeType, it will check if { System.RuntimeType, System.RuntimeType } all are assignable to BaseController

This misunderstanding seems to be recurring over and over again. Maybe we can detect misuse and throw a better description.

Maybe I'm too naive here but could we not make this AllBeAssignableTo work "as expected" instead of throwing a better description?

Fair enough. We could just fix it internally. If the collection is of type IEnumerable<RuntimeTypeInfo or IEnumerable<Type>, it does what you expext it to do.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

shift-evgeny picture shift-evgeny  路  5Comments

robvanuden picture robvanuden  路  5Comments

carlin-q-scott picture carlin-q-scott  路  4Comments

jsmarsch picture jsmarsch  路  3Comments

godrose picture godrose  路  5Comments