我试图模拟没有'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:'无法设置 参数0(Byte []),因为它不是out或ref参数。'
还有其他方法可以更改void方法内的参数吗?
答案 0 :(得分:0)
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);
该代码仍将引用“旧”数组,而不是“新”数组(您尝试嘲笑)。
因此,您将需要将参数提供为ref
或out
,以在您的调用代码中反映该修改。
如果您知道数组将始终包含四个元素,则可以修改数组内容,而不是其引用:
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;
});
因此,您不想将任何调用与NextBytes
匹配,而是只将提供四个字节的数组的调用与之匹配,从而使您的Arg.Any<byte[]()>
有效 strong> a Arg.Is<byte[]>(x => x.Lengh == 4)
。
答案 1 :(得分:0)
感谢 HimBromBeere ,我发现自己做错了。
所以我不能用新的填充字节数组传递数据,我需要替换数组中的每个项目
import 'package:flutter/material.dart';
class CalculateCGPAScreen extends StatelessWidget {
final int noOfSubjectsCount;
CalculateCGPAScreen(this.noOfSubjectsCount);
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(),
body: Column(
children: noOfSubjects(noOfSubjectsCount),
),
);
}
List<Widget> noOfSubjects(int subjectCount) {
List<Widget> list = [];
for (int i = 1; i <= subjectCount; i++) {
list.add(GradeScreen("Subject $i", 1));
}
list.add(RaisedButton(
onPressed: () {},
color: Colors.amber,
splashColor: Colors.amberAccent,
child: Text("Calculate CGPA"),
));
return list;
}
}
class GradeScreen extends StatefulWidget {
final String subjectName;
final int gradeSystem;
int _data;
GradeScreen(this.subjectName, this.gradeSystem);
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _GradeScreenState();
}
set data(int value) {
_data = value;
}
get data => _data;
}
class _GradeScreenState extends State<GradeScreen> {
String selectedGrade = "S";
List<int> creditList = [1, 2, 3, 4, 5, 6];
int selectedCredit = 1;
@override
Widget build(BuildContext context) {
// TODO: implement build
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(widget.subjectName),
DropdownButton(
items: getGradeList(widget.gradeSystem).map((String loopValue) {
return DropdownMenuItem(
child: Text(loopValue),
value: loopValue,
);
}).toList(),
onChanged: (String value) {
setState(() {
selectedGrade = value;
});
},
value: selectedGrade,
),
DropdownButton(
items: creditList.map((int credit) {
return DropdownMenuItem(
child: Text(credit.toString()),
value: credit,
);
}).toList(),
onChanged: (int value) {
setState(() {
selectedCredit = value;
widget.data = selectedCredit;
});
},
value: selectedCredit,
)
],
);
}
List<String> getGradeList(int option) {
List<String> gradeSystem;
if (option == 1) {
gradeSystem = ['S', 'A', 'B', 'C', 'D', 'E'];
} else {
gradeSystem = ['O', 'A+', 'A', 'B+', 'B'];
}
return gradeSystem;
}
}