【问题标题】:Use class in the test's inlineData在测试的 inlineData 中使用类
【发布时间】:2019-10-07 15:51:05
【问题描述】:

我使用以下类作为我的模拟类:

public class MockData
{
    public static MockData Current { get; } = new MockData();
    public List<ClientViewModel> Choices { get; set; }

    public MockData()
    {
        Choices = new List<ClientViewModel>
        {
            new ClientViewModel { Answers = new[] { false, false, false } },
            new ClientViewModel { Answers = new[] { true, true, true } },
            new ClientViewModel { Answers = new[] { true, true, false } },
            new ClientViewModel { Answers = new[] { true, false, true } },
            new ClientViewModel { Answers = new[] { true, false, false } }
        };
    }
}

现在我正在尝试测试上述用户选择,看看ClientViewModel 类的每个实例是否给了我预期的字符串答案。为此,我使用了以下测试方法:

[Fact]
public void ClientRequest_UserChoicesPassed_ReturnsRightAnswer()
{
    // Arrange
    var clientViewModel = MockData.Current.Choices[0];

    // Act
    var jsonResult = _controller.ClientRequest(clientViewModel) as JsonResult;

    // Assert
    string expectedAnswer = "It is a book";
    Assert.Equal(expectedAnswer, ((ResultDTO)jsonResult.Value).Result);
}

这很好用,我的测试按预期通过了。但是我对这种方法的问题是我也必须对其他条目重复此测试,正如您注意到我在测试的Arrange 部分中使用了var clientViewModel = MockData.Current.Choices[0]; 来测试第一个条目,我不想要为此目的编写多个测试来重复我自己。我已经知道 xNunit 中的 [Theory][InlineData] 概念,但是,我似乎在上课时遇到了一些困难,请参见下文:

[Theory]
[InlineData(MockData.Current.Choices[0], "It is a book")]
[InlineData(MockData.Current.Choices[1], "It is a pen")]
public void ClientRequest_UserChoicesPassed_ReturnsRightAnswer(ClientViewModel clientViewModel, string expectedAnswer)
{
  //...
}

但这给了我以下例外:

属性参数必须是属性参数类型的常量表达式、typeof表达式或数组创建表达式

所以请告诉我,有什么办法,我可以做些什么来防止重复这种方法吗?

【问题讨论】:

  • 如您所见,您不能在属性中使用非常量数据。如果你想使用这样的动态数据,你应该使用MemberDataAttribute 并提供一个产生测试用例数据的方法,或者ClassDataAttribute 使用一个实现 IEnumerable 并返回你的测试用例数据的类。

标签: c# unit-testing asp.net-core xunit


【解决方案1】:

为此,您可以使用MemberDataAttribute 和一个公共静态方法,该方法返回您要使用的测试用例。这是一个例子:

public static IEnumerable<object[]> GetUserChoiceTestData() 
{
    yield return new object[] { MockData.Current.Choices[0], "It is a book" };
    yield return new object[] { MockData.Current.Choices[1], "It is a pen" };
}

然后,您将像这样应用到您的测试理论:

[Theory]
[MemberData(nameof(GetUserChoiceTestData))]
public void ClientRequest_UserChoicesPassed_ReturnsRightAnswer(ClientViewModel clientViewModel, string expectedAnswer)
{
  //...
}

只要静态方法是您正在运行的测试类的成员,这将起作用。如果它是另一个非静态类的成员,则需要另外将该类型提供给 MemberDataAttribute

[MemberData(nameof(SomeOtherClass.GetUserChoiceTestData), MemberType = typeof(SomeOtherClass))]

【讨论】:

    猜你喜欢
    • 2020-01-21
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 2015-05-05
    • 2018-11-02
    • 2016-12-31
    • 1970-01-01
    相关资源
    最近更新 更多