Search code examples
c#asp.net-mvcunit-testingt4mvcfluent-assertions

Fluent Assertions ThatAreNotDecoratedWith


I would like to use FluentAssertions to test for all methods that are not decorated with the NonActionAttribute (this will reduce the set of action methods automatically generated as placeholders by T4MVC).

My specific problem is with chaining together MethodInfoSelector methods. I would like to write something like this:

   public MethodInfoSelector AllActionMethods() {
        return TestControllerType.Methods()
            .ThatReturn<ActionResult>()
            .ThatAreNotDecoratedWith<NonActionAttribute>();
   }

    public static MethodInfoSelector ThatAreNotDecoratedWith<TAttribute>(this IEnumerable<MethodInfo> selectedMethods) {
        return (MethodInfoSelector)(selectedMethods.Where(method => !method.GetCustomAttributes(false).OfType<TAttribute>().Any())); // this cast fails
    }

Either the cast fails, or if I convert my results to IEnumerable<MethodInfo> I can't chain additional MethodInfoSelector methods.

I would appreciate any help with either how to generate a MethodInfoSelector or a different approach to the underlying problem of listing methods that do not have a specific attribute.


Solution

  • Fluent Assertions currently has no publicly exposed members to allow you to do this. Your best solution is to go over to the Fluent Assertions project on GitHub and either open an Issue or submit a Pull Request in order to get this fixed in the FA code base.

    I realize this might be viewed as a non-answer, so for completeness I will throw out that you could solve this problem using reflection, though the usual disclaimers about reflecting on private members apply. Here is one such implementation that will let chaining work:

    public static MethodInfoSelector ThatAreNotDecoratedWith<TAttribute>( this MethodInfoSelector selectedMethods)
    {
        IEnumerable<MethodInfo> methodsNotDecorated = selectedMethods.Where(
            method =>
                !method.GetCustomAttributes(false)
                    .OfType<TAttribute>()
                    .Any());
    
        FieldInfo selectedMethodsField =
            typeof (MethodInfoSelector).GetField("selectedMethods",
                BindingFlags.Instance | BindingFlags.NonPublic);
    
        selectedMethodsField.SetValue(selectedMethods, methodsNotDecorated);
    
        return selectedMethods;
    }