Search code examples
c#.net-corexunitxunit.netxunit2

C# each attribute should execute the TestMethod


I have created a custom xUnit theory test DataAttribute named RoleAttribute:

public class RoleAttribute : DataAttribute
{
    public Role Role { get; set; }
    public RoleAttribute(Role role, Action<Role> method)
    {
        Role = role;
        AuthRepository.Login(role);
        method(role);
    }

    public override IEnumerable<object[]> GetData(MethodInfo testMethod)
    {
        return new[] { new object[] { Role } };
    }
}

And I have the test method OpenProfilePageTest:

public class ProfileTest : AuthTest
{
    [Theory, Priority(0)]
    [Role(Enums.Role.SuperUser, OpenProfilePageTest)]
    [Role(Enums.Role.Editor, OpenProfilePageTest)]
    public void OpenProfilePageTest(Enums.Role role)
    {
        var profile = GetPage<ProfilePage>();
        profile.GoTo();
        profile.IsAt();
    }
}

What I want is that for each role (attribute) it executes first:

AuthRepository.Login(role); (constructor of RoleAttribute)

and then resumes with the code inside OpenProfilePageTest() method. Before it repeats the same but for the second attribute.

How can I accomplish this, right now I'm trying to accomplish this by passing the OpenProfilePageTest() method inside the attribute and execute it in its constructor. There must be a better way to accomplish this than passing around the method I believe?


Solution

  • You can achieve this without passing the method, you need to modify your attribute slightly. I changed the attribute to take all the roles you want to test and return them in the data. Here is an example

    public class RolesAttribute : DataAttribute
    {
        private Role[] _roles;
        public RolesAttribute(params Role[] roles)
        {
            _roles = roles;
        }
    
        public override IEnumerable<object[]> GetData(MethodInfo testMethod)
        {
            var data = new List<object[]>();
            //We need to add each role param to the list of object[] params
            //This will call the method for each role
            foreach(var role in _roles)
                data.Add(new object[]{role});
            return data;
        }
    }
    

    Then in your test, you just pass all the roles you want to test in a single attribute like so

    public class ProfileTest : AuthTest
    {
        [Theory, Priority(0)]
        [Roles(Enums.Role.SuperUser, Enums.Role.Editor)]
        public void OpenProfilePageTest(Enums.Role role)
        {
            AuthRepository.Login(role);
            var profile = GetPage<ProfilePage>();
            profile.GoTo();
            profile.IsAt();
        }
    }