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
参数。由于参数不是 ref
或 out
,更改模拟成员中的数组引用不会对调用代码产生任何影响。你这样做很有效:
class TheMoc : IRandomNumberGenerator
{
public void NextBytes(byte[] bytes)
{
bytes = new byte[] {0x4d, 0x65, 0x64, 0x76};
}
}
这当然不会反映在调用代码中。这就是 NSubsitute 给你例外的原因。
话虽如此,您并不清楚为什么要这样做,因为您调用的代码 永远不会 反映您的 实际 实现接口与该数组有关。
因此当您的调用代码如下所示时:
theGenerator.NextBytes(bytes);
该代码仍将引用 "old" 数组,而不是 "new" 数组(您试图模拟)。
因此,您将 需要提供参数 ref
或 out
以在您的调用代码中反映该修改。
如果你知道你的数组总是有四个元素,你可以只修改数组 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;
});
所以您不想匹配 any 对 NextBytes
的调用,而只匹配那些提供四字节数组的调用,使您的 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;
});
我试图在没有 '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
参数。由于参数不是 ref
或 out
,更改模拟成员中的数组引用不会对调用代码产生任何影响。你这样做很有效:
class TheMoc : IRandomNumberGenerator
{
public void NextBytes(byte[] bytes)
{
bytes = new byte[] {0x4d, 0x65, 0x64, 0x76};
}
}
这当然不会反映在调用代码中。这就是 NSubsitute 给你例外的原因。
话虽如此,您并不清楚为什么要这样做,因为您调用的代码 永远不会 反映您的 实际 实现接口与该数组有关。
因此当您的调用代码如下所示时:
theGenerator.NextBytes(bytes);
该代码仍将引用 "old" 数组,而不是 "new" 数组(您试图模拟)。
因此,您将 需要提供参数 ref
或 out
以在您的调用代码中反映该修改。
如果你知道你的数组总是有四个元素,你可以只修改数组 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;
});
所以您不想匹配 any 对 NextBytes
的调用,而只匹配那些提供四字节数组的调用,使您的 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;
});