【发布时间】:2021-07-29 02:02:21
【问题描述】:
我负责测试我的团队正在维护的用 C 和 C# 开发的遗留软件。最初的团队使用 NSubstitute 3.1 为代表创建测试替身,以便对 C# 部分的 API 执行单元测试。这是一个这样的测试替身,省略了不相关的细节:
private static byte[] MockSelectByAidWithoutData(ushort retVal)
{
var expectedIn= "FFFEFDFCFB".HexToBytes();
var expectedOut= "010203040506070809".HexToBytes();
var fake = Substitute.For<SomeDelegate>();
fake(Arg.Is<byte[]>(x => expectedIn.SequenceEqual(x.Take(expectedIn.Length))),
Arg.Is(0x00),
Arg.Is(expectedIn.Length),
Arg.Any<int>(),
Arg.Any<int>(),
out int outputLength)
.Returns(x =>
{
expectedOut.CopyTo((Array)x[0], 0);
x[5] = expectedOut.Length;
return retVal;
}
);
Mediator.GetInstance().Delegate = fake;
return expectedOut;
}
现在,如果使用与 fake() 调用中指定的参数匹配的参数调用假委托,它会返回 retVal 值,每个人都很高兴。但是,如果某些值不匹配,则返回零。由于零是一个有效但不正确的值,因此继续执行,我得到一个错误,这不是我正在测试的问题的根本原因(即当问题实际上是错误输入时输出错误)
我正在寻找一种方法:
- 为不符合预期的值指定“包罗万象”行为,或
- 如果参数与预期不符,则会出现异常
这样测试用例会在接收到带有有意义消息的错误输入时立即失败,并且不会触发只会污染测试结果的进一步行为。
提前致谢,
德克
附:如果真的有必要,我可能可以安全地切换到更新版本的 NSubstitute。
【问题讨论】:
-
我认为您需要使用
Received来断言使用特定参数进行了调用。如果这将复制来自Returns存根的逻辑,您可能会使用ReturnsForAnyArgs进行切换,并且仅匹配Received断言中的参数。 -
这类似于我正在使用的解决方法,我只接受对 fake() 的调用中的任何参数,然后使用 AndDoes 在回调中手动执行所有断言。 (Received 部分永远不会执行,因为 retval = 0 会触发异常。)但是我不太喜欢这种解决方法:我正在手动执行框架应该为我做的事情。似乎我只是使用了错误的工具来完成这项工作。
标签: c# unit-testing mocking nunit nsubstitute