NSubstitute 模拟一个没有 out/ref 参数的 void 方法

NSubstitute mock a void method without out/ref parameters

我试图在没有 'out' 或 'ref' 参数的情况下模拟一个 void 方法,但我无法模拟它。 我想修改模拟函数中的参数

public interface IRandomNumberGenerator
{
    void NextBytes(byte[] buffer);
}

var randomImplementation = Substitute.For<IRandomNumberGenerator>();    
randomImplementation.When(x => x.NextBytes(Arg.Any<byte[]>())).Do(x =>
{
    x[0] = new byte[] {0x4d, 0x65, 0x64, 0x76};
});

但是当我运行这个测试得到错误:

NSubstitute.Exceptions.ArgumentIsNotOutOrRefException: 'Could not set argument 0 (Byte[]) as it is not an out or ref argument.'

是否有任何其他可能在 void 方法中更改参数?

x[0] 指传递给 NextBytes 的第一个参数,在您的例子中是 buffer 参数。由于参数不是 refout,更改模拟成员中的数组引用不会对调用代码产生任何影响。你这样做很有效:

class TheMoc : IRandomNumberGenerator
{
    public void NextBytes(byte[] bytes)
    {
        bytes = new byte[] {0x4d, 0x65, 0x64, 0x76};
    }
}

这当然不会反映在调用代码中。这就是 NSubsitute 给你例外的原因。

话虽如此,您并不清楚为什么要这样做,因为您调用的代码 永远不会 反映您的 实际 实现接口与该数组有关。

因此当您的调用代码如下所示时:

theGenerator.NextBytes(bytes);

该代码仍将引用 "old" 数组,而不是 "new" 数组(您试图模拟)。

因此,您 需要提供参数 refout 以在您的调用代码中反映该修改。

如果你知道你的数组总是有四个元素,你可以只修改数组 content,而不是它的 reference:

randomImplementation.When(x => x.NextBytes(Arg.Any<byte[]>())).Do(x =>
{
    x[0][0] = 0x4d;
    x[0][1] = 0x65;
    x[0][2] = 0x64;
    x[0][3] = 0x76;
});

所以您不想匹配 anyNextBytes 的调用,而只匹配那些提供四字节数组的调用,使您的 Arg.Any<byte[]()> 有效一个Arg.Is<byte[]>(x => x.Lengh == 4).

感谢 HimBromBeere 我明白了我做错了什么。

所以我不能用新的填充字节数组传递,我需要替换数组中的每个项目

public interface IRandomNumberGenerator
{
    void NextBytes(byte[] buffer);
}

var randomImplementation = Substitute.For<IRandomNumberGenerator>();    
randomImplementation.When(x => x.NextBytes(Arg.Any<byte[]>())).Do(x =>
{
    var byteArray = x.Arg<byte[]>();
    byteArray [0] = 0x4d;
    byteArray [1] = 0x65;
    byteArray [2] = 0x64;
    byteArray [3] = 0x76;
});