theateist
theateist

Reputation: 14411

DynamicData doesn't populate correctly test data when using grpc objects

I use Visual Studio 2022 and MS Test. To generate code from proto file I use Grpc.Tools (2.69.0) and Google.Protobuf (3.29.3) nugets.

I don't know how DynamicData feature works under the hood, but it seems it doesn't populate correctly the step object when the code is generated with protobuf compiler.

Case1:

Step, Element1 and Element2 are generated with protobuf compiler. When TestMethod is invoked the step's Elements are null (see image below).

Case2:

I manually create Step and Element1 and Element2 classes without protobuf compiler. In this case the step's elements are not null.

enter image description here

MS Test

namespace TestProject
{
    [TestClass]
    public class UnitTest
    {
        [TestMethod]
        [DynamicData(nameof(GetTestData), typeof(UnitTest), DynamicDataSourceType.Method)]
        public void TestMethod(Step step)
        {
        }

        public static IEnumerable<object[]> GetTestData()
        {
            yield return new object[] { Step_Element1() };
            yield return new object[] { Step_Element2() };
        }

        private static Step Step_Element1()
        {
            var step = new Step();
            step.Elements.Add(new Element { Element1 = new Element1() });
            return step;
        }

        private static Step Step_Element2()
        {
            var step = new Step();
            step.Elements.Add(new Element { Element2 = new Element2() });
            return step;
        }
    }
}

command.proto

syntax = "proto3";

message Step {
    repeated Element elements = 1;
}

message Element1 {
}

message Element2 {
}

message Element {
    oneof value {
        Element1 element1 = 1;
        Element2 element2 = 2;
    }
}

Upvotes: 1

Views: 41

Answers (1)

Youssef13
Youssef13

Reputation: 4986

This is due to the way parameterized tests work. The arguments of the test method are serialized during discovery, and then deserialized during execution. If Step isn't serializable, then it won't work.

One way to fix this is to have your test method "folded" (aka not expanded) during discovery. That way, your test method is treated as a single test case. However, during execution, the data will be retrieved and all test cases will run. In TRX and IDE, it will show as a single test case with multiple results. You do this by setting UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Fold on DynamicDataAttribute. This assumes that you are on latest MSTest.

Also note that DynamicDataSourceType.Method is no longer required with latest MSTest, and specifying the type (typeof(UnitTest)) is also unnecessary. So, the attribute can be as follows:

[DynamicData(nameof(GetTestData), UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Fold)]

Upvotes: 0

Related Questions