c# - 如何在 NSubstitute 3.1 中使用 ref 参数引发委托事件?
问题描述
我正在开发一个使用 3rd 方库的 C# 项目。这个库使用 ref 参数定义了一个相当不寻常的委托事件:
event GetDataHandler OnGetData;
public delegate bool GetDataHandler(string name, ref byte[] data);
我试图通过 NSubstitute(版本 3.1)在单元测试中引发此事件,但我无法让它工作。我尝试了这段代码(基本上是我能想到的所有变体):
var theKey = "test";
byte[] theData = null;
_theObject.OnGetData += Raise.Event<GetDataHandler>(theKey, ref theData);
但这不会编译。编译器说:参数 2 不能使用 'ref' 关键字传递。
我知道 NSubstitute 4.x 的 out/ref 机制已经改变,但我的公司还没有升级到更新的版本。
有没有办法使用 NSubstitute 3.1 来启动和运行它?非常感谢!
最好的问候,奥利弗
解决方案
该Raise.Event
重载将参数作为params object[]
. 我们可以在这个 params 数组中将 byref 字节数组作为标准值传递(这意味着我们不会为我们传递的事件 args 获得编译时安全性,但是如果我们弄错了,测试会很快发现它:) ):
_theObject.OnGetData += Raise.Event<GetDataHandler>("name", theData);
这是一个可执行的示例:
using NSubstitute;
using Xunit;
public delegate bool GetDataHandler(string name, ref byte[] data);
public interface ISomeType {
event GetDataHandler OnGetData;
}
public class SampleFixture {
string lastNameUsed = "";
byte[] lastBytesUsed = new byte[0];
[Fact]
public void SomeTest() {
var sub = Substitute.For<ISomeType>();
var data = new byte[] { 0x42 };
sub.OnGetData += Sub_OnGetData;
sub.OnGetData += Raise.Event<GetDataHandler>("name", data);
Assert.Equal("name", lastNameUsed);
Assert.Equal(data, lastBytesUsed);
}
private bool Sub_OnGetData(string name, ref byte[] data) {
lastNameUsed = name;
lastBytesUsed = data;
return true;
}
}
在评论中提供更多信息后进行编辑。
我认为 NSubstitute 不支持检查在这种情况下返回的值。
在不确切知道您要测试什么的情况下,我可以建议几种通用方法来测试此类事情。
第一个选项是手动编写一个ISomeType
您可以完全控制的测试替身(在这种情况下是 的实现)。除非界面很大,否则我会推荐这种方法。
另一种选择是分别测试委托和连线。例如,给定这个类:
public class ClassUnderTest {
public ClassUnderTest(ISomeType dep) {
dep.OnGetData += Dep_OnGetData;
}
public static bool Dep_OnGetData(string name, ref byte[] data) {
data = System.Text.Encoding.UTF8.GetBytes(name);
return true;
}
}
我们可以独立测试委托,然后测试我们已经连接了该委托:
[Fact]
public void TestDelegate() {
byte[] data = new byte[0];
var result = ClassUnderTest.Dep_OnGetData("hi", ref data);
Assert.True(result);
Assert.Equal(new byte[] { 104, 105 }, data);
}
[Fact]
public void TestWireup() {
var sub = Substitute.For<ISomeType>();
var subject = new ClassUnderTest(sub);
sub.Received().OnGetData += ClassUnderTest.Dep_OnGetData;
}
我认为这种情况下的委托测试可能非常有用,但是连接测试可能不是很好,因为它非常特定于特定的实现,而不是所需的行为/结果。但在这种情况下,很难观察到特定的效果,因此这是一个潜在的答案。
第三,我们也许可以对所讨论的库使用更可测试的包装器。或者这个测试可能完全处于错误的级别——要警惕我们不拥有的模拟类型。(我在这里写了一些关于这个的内容。)
如果您可以提供更多关于您在这种情况下要测试的内容的信息,我很乐意尝试提出更合理的答案。:)
推荐阅读
- excel - 从 Excel 连接时 BE Access 数据库膨胀
- python-3.x - 如何将列表中的某些项目组合在一起 - Python3
- react-native - 你什么时候使用 react-native-push-notification 与 @react-native-community/push-notification-ios?
- php - Symfony - 表单未重定向到表单中指定的操作
- ruby-on-rails - 保持列表项的原始选择顺序
- html - 一首歌曲完成后如何设置自动播放、循环播放和多首歌曲?
- angular - 使用 Karma 和 Jasmine / Angular 8 对具有多个 API 调用的服务进行单元测试
- node.js - 为什么我获取的承诺以未决结果结束
- javafx-8 - 拖放单个单元格 JAVAFX
- jenkins - 我可以通过 github 插件传递 jenkins 作业参数吗