Ackdari
Ackdari

Reputation: 3508

Specifying the return value for xUnit Theory tests

Is it possible to specify the return value for a theory case? Like I have the test methode:

[Theory]
[MemberData(nameof(TestCases))]
public async Task<bool> Test(int i, double d, string str)
{
    return DoStuffAsync(i, d, str);
}

and the methode

public static IEnumerable<object[]> TestCases()
{
    yield return new object[] { 1, Math.PI, "case1", true };
    yield return new object[] { 2, Math.E,  "case2", false };
}

to produce the test cases.

But if I try to run these test cases, I get the error

System.InvalidOperationException : The test method expected 3 parameter values, but 4 parameter values were provided.

Upvotes: 4

Views: 3350

Answers (2)

Pavel Anikhouski
Pavel Anikhouski

Reputation: 23308

You can rewrite your test a little bit, by adding the parameter for expected result and compare it in Assert with value, returned from DoStuffAsync method. Also don't forget to change the return value for test method from Task<bool> to just Task or async void, since you are checking the return value inside test and return nothing

[Theory]
[MemberData(nameof(TestCases))]
public async Task Test(int i, double d, string str, bool expected)
{
    var result = await DoStuffAsync(i, d, str);
    Assert.Equal(expected, result);
}

Upvotes: 5

dodekja
dodekja

Reputation: 565

You can't specify a return value to a theory test case, but you can add a parameter which acts like an expected value, and compare the test output to this value. In this case, the test would look like this:

[Theory]
[MemberData(nameof(TestCases))]
public async Task Test(int i, double d, string str, bool expectedValue)
{
     bool actualValue = DoStuffAsync(i, d, str);
     Assert.True(actualValue == expectedValue);
}

This will tell the framework if the expected value is equal to the actual value produced by the DoStuffAsync method. The Assert statement is used to evaluate if the test passed or failed.

Yet another, probably much easily maintainable approach is to split one test into two. In the first one, you can expect the method output to be true for each case, and in the second you can expect the output to be false for each case.

First test should look like this

[MemberData(nameof(TestCasesTrue))]
public async Task TestTrue(int i, double d, string str)
{
     bool actualValue = DoStuffAsync(i, d, str);
     Assert.Equal(true, actualValue);
}

And the second test like this:

[MemberData(nameof(TestCasesFalse))]
public async Task TestFalse(int i, double d, string str)
{
     bool actualValue = DoStuffAsync(i, d, str);
     Assert.Equal(false, actualValue);
}

Upvotes: 2

Related Questions