使用 TestCaseData 参数检查异常

Checking exceptions with TestCaseData parameters

我正在使用 NUnit 3 TestCaseData 对象将测试数据提供给测试,并使用 Fluent Assertions 库检查抛出的异常。

通常我的 TestCaseData 对象包含两个参数 param1param2 用于在测试中创建某个对象的实例,然后我调用 should/should 不会抛出异常,像这样:

var subject = new Subject(param1, param2);
subject.Invoking(s => s.Add()).Should().NotThrow();

var subject = new Subject(param1, param2);
subject.Invoking(s => s.Add()).Should().Throw<ApplicationException>();

有没有办法将NotThrow()Throw<ApplicationException>()部分作为特定条件传递到TestCaseData对象的第三个参数中以用于测试?基本上我想参数化测试的预期结果(它可能是某种类型的异常或根本没有异常)。

[TestCaseData] 适用于 测试用例数据 ,不适用于断言方法。

我会在单独的测试中保留 NotThrowThrow 以保持可读性。 如果他们共享很多设置逻辑,我会提取 that 到共享方法中以减少测试方法主体的大小。

TestCaseData 接受编译时值,而 TestCaseSource 在运行时生成它们,这是使用 ThrowNotThrow.

所必需的

这是一种通过滥用 TestCaseSource 来实现的方法。 结果是一个不可读的测试方法,所以请不要在任何地方使用它。

不管怎么说:

[TestFixture]
public class ActionTests
{
    private static IEnumerable<TestCaseData> ActionTestCaseData
    {
        get
        {
            yield return new TestCaseData((Action)(() => throw new Exception()), (Action<Action>)(act => act.Should().Throw<Exception>()));
            yield return new TestCaseData((Action)(() => {}), (Action<Action>)(act => act.Should().NotThrow()));
        }
    }

    [Test]
    [TestCaseSource(typeof(ActionTests), nameof(ActionTestCaseData))]
    public void Calculate_Success(Action act, Action<Action> assert)
    {
        assert(act);
    }
}

我最终使用了这个:

using ExceptionResult = Action<System.Func<UserDetail>>;

        [Test]
        [TestCaseSource(typeof(UserEndpointTests), nameof(AddUserTestCases))]
        public void User_Add(string creatorUsername, Role role, ExceptionResult result)
        {
            var endpoint = new UserEndpoint(creatorUsername);
            var person = GeneratePerson();
            var request = GenerateCreateUserRequest(person, role);

            // Assertion comes here
            result(endpoint.Invoking(e => e.Add(request)));
        }

        private static IEnumerable AddUserTestCases
        {
            get
            {
                yield return new TestCaseData(TestUserEmail, Role.User, new ExceptionResult(x => x.Should().Throw<ApplicationException>())
                    .SetName("{m} (Regular User => Regular User)")
                    .SetDescription("User with Regular User role cannot add any users.");

                yield return new TestCaseData(TestAdminEmail, Role.Admin, new ExceptionResult(x => x.Should().NotThrow())
                    )
                    .SetName("{m} (Admin => Admin)")
                    .SetDescription("User with Admin role adds another user with Admin role.");
            }
        }

可读性没有大问题,此外,测试用例源代码中的 SetName()SetDescription() 方法对此有帮助。