6

I am performing some unit test using MSTest and I learned that I can use the [DynamicData] attribute to input different cases for testing, but I can't use the attribute property: DynamicDataDisplayName to set a name for the different cases.

My test code is:

    [TestMethod]
    [DynamicData(nameof(TestInputs_BeReady), DynamicDataSourceType.Method,
        DynamicDataDisplayName = nameof(GetTestDisplayNames),
        DynamicDataDisplayNameDeclaringType = typeof(List<string>))]
    public void Should_BeReady(object expValue, object[] inputs)
    {
        // Arrange

        // Act
        ui.InputID = (string)inputs[0];
        ui.InputName = (string)inputs[1];
        ui.InputList = (List<string>)inputs[2];

        // Assert
        Assert.AreEqual(expValue, onReadyStateChangeArgs.Ready);
    }

    public static IEnumerable<object[]> TestInputs_BeReady()
    {
        return new[]
        {
            new object[] { true, new object[] { "UTSZ0", "Unit Test Size List" , new List<string> { "entry_01", "entry_02" } } },
            new object[] { false, new object[] { "STEST", "Unit Test Size List" , new List<string> { "entry_01", "entry_02" } } },
            new object[] { false, new object[] { "", "Unit Test Size List" , new List<string> { "entry_01", "entry_02" } } },
            new object[] { false, new object[] { "UTSZ0", "" , new List<string> { "entry_01", "entry_02" } } },
            new object[] { false, new object[] { "UTSZ0", "Unit Test Size List", new List<string>() } },
            new object[] { false, new object[] { "UTSZ0", "Unit Test Size List", null } }
        };
    }

    public static IEnumerable<string> GetTestDisplayNames() => new List<string> {
        "All Valid", "Duplicate ID", "Missing ID", "Missing Name", "Empty List", "Null List"
    };

And I am getting this message in the test explorer result:

Message: Value cannot be null.

Parameter name: Method GetTestDisplayNames

I searched the web on how to use the DynamicDataDisplayName but I was unable to come with something; all I found is how to use DynamicData


EDIT

I used this code to add a customized names for the test inputs, thanks to

Matěj Pokorný

    [TestMethod]
    [DynamicData(nameof(TestInputs_BeReady), DynamicDataSourceType.Method,
        DynamicDataDisplayName = nameof(GetTestDisplayName))]
    public void Should_DoSomething(object expValue, object[] inputs, string _)
    {
        // Arrange
        // Act
        // Assert
    }
    public static IEnumerable<object[]> TestInputs_BeReady()
    {
        List<string> ITEMS_LIST = new List<string> { "entry_01", "entry_02" };
        List<string> BLANK_LIST = new List<string>();

        return new[]
        {
            new object[] {  true, new object[] { UQID, NAME, ITEMS_LIST }, "All Valid" },
            new object[] { false, new object[] { DPID, NAME, ITEMS_LIST }, "Duplicate ID" },
            new object[] { false, new object[] { BLNK, NAME, ITEMS_LIST }, "Missing ID" },
            new object[] { false, new object[] { UQID, BLNK, ITEMS_LIST }, "Missing Name" },
            new object[] { false, new object[] { UQID, NAME, BLANK_LIST }, "Empty List" },
            new object[] { false, new object[] { UQID, NAME, null }, "Null List" }
        };
    }
Taher
  • 565
  • 1
  • 14
  • 32

1 Answers1

6

The issue is with GetTestDisplayNames method. You should define it like this

public static string GetTestDisplayNames(MethodInfo methodInfo, object[] values)
{
    var expected = (bool)values[0];
    var inputs = (object[])values[1];
    
    return $"{methodInfo.Name}({expected}, {inputs.Length})";
}

(this is a possible implementation, but you can return a different name of course)

Also, parameter DynamicDataDisplayNameDeclaringType should point to type, where is GetTestDisplayNames method defined. I believe, when you have this method defined in same class as test method (Should_BeReady), this parameter can be skipped.

Matěj Pokorný
  • 16,977
  • 5
  • 39
  • 48
  • Ok. But this won't return customized names like "All Valid", "Duplicate ID", ..., etc. Anyways, thanks. I will poke and tamper with this code to see what else I can do. – Taher Jan 09 '22 at 09:42
  • 1
    Yep, this is not possible, because `index` of the currently running test case can't be obtained from `GetTestDisplayNames` method. The best, you can do, is to include something into returned `object[]` (in `TestInputs_BeReady`) and then use it in `GetTestDisplayNames` method... – Matěj Pokorný Jan 10 '22 at 11:37
  • 1
    Yes, this is what I found out during my tests. I will try and modify the question with some code to help others. Thanks @Matěj Pokorný – Taher Jan 10 '22 at 12:18