在测试的inlineData中使用类

时间:2019-10-07 15:51:05

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

我将以下课程用作模拟课程:

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);
}

这非常有效,并且我的测试已按预期通过。但是,这种方法的问题在于,我也必须对其他条目重复此测试,正如您所注意到的,我在测试的var clientViewModel = MockData.Current.Choices[0];部分中使用了Arrange来测试第一个条目,即不想为此编写多个测试来重复自己。我已经知道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表达式或数组创建表达式

所以请让我知道,有什么办法,我能做些什么来防止重复这种方法?

1 个答案:

答案 0 :(得分:4)

要实现此目的,可以将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))]