在单元测试中使用 InlineData 的困难 - 参数是一个控制器

Difficulties using InlineData in Unit Test - parameter is a controller

我是测试新手,现在正在学习使用 xUnit。

我已经编写了下面的测试,它有效并给出了我正在寻找的结果,但我认为我应该能够使它更干净,就像在 nUnit 中使用 TestCase 时一样。因此,我正在尝试使用 InlineData,我知道它是 xUnits "TestCase",但我不知道该怎么做。

尝试设置时,如下所示(请查看注释掉的行),然后它告诉我

    [Theory]
    // [InlineData("")] // wanna use InlineData just to make the code/test cleaner.
    // [InlineData(null)]
    public async Task Get_Return_Something(
        MyController sut)
    {
        var result1 = await sut.Get(""); // when placing "sut" as param, I get: cannot convert from MyController to string. 
        var result2 = await sut.Get(null); // same applies here..

        result1.ShouldBeOfType(typeof(OkObjectResult));
        result2.ShouldBeOfType(typeof(BadRequestObjectResult));
    }

我的问题是 - 如何实现 InlineData 以便测试更清晰。当我有一个控制器作为参数时甚至可能吗?

澄清一下 -> 是否有办法使用 nUnit 的语法:

// something like this
[TestCase("", OkObjectResult)]
[TestCase(null, BadRequestObjectResult)]
public async Task Get_Return_Something(MyController sut, param1, param2)
{
    var result = await.sut.Get(param1);
    result.ShouldBeOfType(typeof(param2));
}

也许 nUnit 示例不正确 - 但我试图通过说出更清晰的代码来指出我正在寻找的东西。通过遵循测试用例逻辑,我可以轻松地将我的测试扩展到 10-15 个不同的测试用例。我听说 xUnit 对 InlineData 做了类似的事情(LasseVågsætherKarlsen 告诉我这是不可能的) - 或者 MemberClass 或 ClassData。

可能性 1

  1. 创建 MyControllerClassData
    public class MyControllerClassData : IEnumerable<object[]>
    {
        public IEnumerator<object[]> GetEnumerator()
        {
            yield return new object[] {
                new MyController
                {
                  Id = 1,
                  // ...
                }
            };
        }
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
  1. 修改你的理论
    [Theory]
    [ClassData(typeof(MyControllerClassData))]
    public async Task Get_Return_Something(MyController sut)
    {
        var result1 = await sut.Get(""); // when placing "sut" as param, I get: cannot convert from MyController to string. 
        var result2 = await sut.Get(null); // same applies here..

        result1.ShouldBeOfType(typeof(OkObjectResult));
        result2.ShouldBeOfType(typeof(BadRequestObjectResult));
    }

可能性 2

  1. 在构造函数中创建 MyController class 并将其存储在私有 属性
  2. 将参数更改为字符串和您想要的objectResult
  3. 始终使用相同的 MyController,使用字符串执行 Get() 并根据预期的 objectResult 对其进行验证。

这个解决方案看起来更清晰一些,因为您对每种情况都有一个测试。

我终于把它修好了。实际上可以使用 InlineData - 只是不像使用 nUnit 那样容易 (imo)。这是解决方案:

[Theory]
[InlineData("", typeof(OkObjectResult))]
[InlineData(null, typeof(BadRequestObjectResult))]
public async Task Get_Return_Something(param1, param2){

    // moq MyController with its parameters/objects
    ...


    var result = await sut.Get(param1);

    result.ShouldBeOfType(param2);
}

在我看来,这是一种非常简单的方法 - 与在网上搜索时找到的方法相比 - 希望它对其他人也有用。