Reputation:
I have used the following class as my Mocked class:
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 } }
};
}
}
Now I am trying to test the above user choices to see if each instance of ClientViewModel
class give me the expected string answer. To achieve this I have used the following test method:
[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);
}
This works perfectly and my test is passed as expected. However my problem with this approach is that I have to repeat this test for other entries as well, as you noticed I have used var clientViewModel = MockData.Current.Choices[0];
in the Arrange
section of the test, to test the first entry, I don't want to repeat myself by writing multiple tests for this purpose. I already aware of [Theory]
and [InlineData]
concepts in xNunit, however, it seems I have some difficulty with class, please see below:
[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)
{
//...
}
But this gives me the following exception:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
So please let me know, is there any way, I can do anything to prevent repeating this method?
Upvotes: 3
Views: 3743
Reputation: 9704
To accomplish this, you can use the MemberDataAttribute
with a public static method that returns your test cases to be used. Here's an example:
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" };
}
Which, you would then apply to your test theory like so:
[Theory]
[MemberData(nameof(GetUserChoiceTestData))]
public void ClientRequest_UserChoicesPassed_ReturnsRightAnswer(ClientViewModel clientViewModel, string expectedAnswer)
{
//...
}
This will work so long as the static method is a member of the test class you are running. If it's a member of another non-static class, you'll need to additionally provide that type to the MemberDataAttribute
.
[MemberData(nameof(SomeOtherClass.GetUserChoiceTestData), MemberType = typeof(SomeOtherClass))]
Upvotes: 8