如何在 NSubstitute 3.1 中使用 ref 参数引发委托事件?



我正在开发一个使用第三方库的 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"关键字一起传递

我知道 out/ref 机制在 NSubstitute 4.x 中发生了变化,但我的公司尚未升级到较新版本。

有没有办法使用 NSubstitute 3.1 启动并运行它?多谢!

此致敬意 奥利弗

Raise.Event重载将参数作为params object[]。我们可以将 byref 字节数组作为这个 params 数组中的标准值传递(这意味着我们不会为我们正在传递的事件参数获得编译时安全性,但如果我们弄错了,测试会很快:)

(:
_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;
}

我认为在这种情况下的委托测试可能非常有用,但连线测试可能不是很好,因为它非常特定于特定的实现,而不是所需的行为/结果。但在这种情况下,观察特定效果是困难的,因此这是一个潜在的答案。

第三,我们也许可以在有问题的库上使用更可测试的包装器。或者这个测试可能完全处于错误的水平——警惕我们不拥有的嘲笑类型。(我在这里写了一些关于这个的文章。

如果您能提供有关在此场景中尝试测试的内容的更多信息,我很乐意尝试提出更合理的答案。 :)

最新更新