为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
湖上湖 2023-09-09 16:18:38
我正在开发一个使用第三方库的 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 启动并运行它吗?多谢!最好的问候,奥利弗
查看完整描述

1 回答

?
烙印99

TA贡献1829条经验 获得超13个赞

该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;

}

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


第三,我们也许能够在相关库上使用更可测试的包装器。或者这个测试可能完全处于错误的级别——警惕我们不拥有的模拟类型。(我在这里写了一些相关内容。)


如果您可以提供有关您在这种情况下尝试测试的内容的更多信息,我很乐意尝试提出更合理的答案。:)


查看完整回答
反对 回复 2023-09-09
  • 1 回答
  • 0 关注
  • 50 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信