简体   繁体   English

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

[英]How to raise a delegate event using a ref parameter in NSubstitute 3.1?

I'm working on a C# project that uses a 3rd party library. 我正在使用第3方库的C#项目中。 This library defines a rather unusual delegate event using a ref parameter: 该库使用ref参数定义了一个非常不寻常的委托事件:

event GetDataHandler OnGetData;
public delegate bool GetDataHandler(string name, ref byte[] data);

I'm trying to raise this event in a unit test via NSubstitute (version 3.1) but I can't get it to work. 我正在尝试通过NSubstitute(版本3.1)在单元测试中引发此事件,但是我无法使其正常工作。 I tried this code (and basically every variation of it that I could think of): 我尝试了这段代码(基本上我可以想到的每个变体):

var theKey = "test";
byte[] theData = null;
_theObject.OnGetData += Raise.Event<GetDataHandler>(theKey, ref theData);

But this does not compile. 但这不能编译。 The compiler says: Argument 2 may not be passed with the 'ref' keyword . 编译器说: 参数2可能不能与'ref'关键字一起传递

I'm aware that the out/ref mechanism has changed with NSubstitute 4.x but my company has not upgraded to the newer version yet. 我知道NSubstitute 4.x的out / ref机制已经更改,但是我的公司尚未升级到较新版本。

Is there any way to get this up and running using NSubstitute 3.1? 有什么办法可以使用NSubstitute 3.1来启动和运行它? Thanks a lot! 非常感谢!

Best regards, Oliver 最好的问候,奥利弗

That Raise.Event overload takes parameters as a params object[] . Raise.Event重载将参数作为params object[] We can pass the byref byte array as a standard value in this params array (which means we don't get compile-time safety for the event args we're passing, but the test will pick this up pretty quickly if we get it wrong :) ): 我们可以在此params数组中将byref字节数组作为标准值传递(这意味着我们对于传递的事件args不会获得编译时的安全性,但是如果我们弄错了,测试会很快地将其提取出来) :)):

_theObject.OnGetData += Raise.Event<GetDataHandler>("name", theData);

Here's an executable example: 这是一个可执行的示例:

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

Edit after more info provided in comment. 在评论中提供更多信息后进行编辑。

I don't think NSubstitute supports inspecting the value that comes back in this case. 我不认为NSubstitute支持检查这种情况下返回的值。

Without knowing exactly what you're trying to test, I can suggest a couple of general approaches for testing this sort of thing. 在不完全知道您要测试的内容的情况下,我可以建议一些用于测试此类内容的一般方法。

First option is to hand code a test double (in this case an implementation of ISomeType ) that you have full control over. 第一种选择是手工编写一个可以完全控制的测试双(本例中为ISomeType的实现)。 Unless the interface is huge, I'd recommend this approach. 除非接口很大,否则我建议使用这种方法。

Another option is to test the delegate and the wire-up separately. 另一种选择是分别测试代表和连线。 For example, given this class: 例如,给定此类:

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

We can test the delegate independently, and then test we've hooked up that delegate: 我们可以独立测试委托,然后测试我们已经将该委托连接起来了:

[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;
}

I think the delegate test in this case is potentially very useful, but the wire-up test is probably not great because it is very specific to the particular implementation, rather than the behaviour/outcome required. 我认为在这种情况下,委托测试可能非常有用,但是连线测试可能并不好,因为它非常特定于特定的实现,而不是所需的行为/结果。 But in this case observing the particular effect is difficult, so it is a potential answer. 但是在这种情况下,很难观察到特定的效果,因此这是一个潜在的答案。

Thirdly, we may be able to use a more testable wrapper over the library in question. 第三,我们也许可以在所讨论的库中使用更具可测试性的包装器。 Or this test may be at the wrong level entirely -- be wary of mocking types we don't own. 或此测试可能完全处于错误的级别-警惕我们不拥有的模拟类型。 (I've written a bit about this here .) (我在这里已经写了一些。)

If you can provide a little more info on what you're trying to test in this scenario I'm happy to try to come up with a more reasonable answer. 如果您可以提供更多有关在这种情况下要测试的内容的信息,我们很乐意为您提供一个更合理的答案。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM