我正在编写单元测试,而我偶然发现了Resharper的建议。
任何执行路径都不使用赋值。
在以下代码snipet中。
[Test]
[TestCase((int)OddsRoundingModes.Floor)]
public void GetBaseOddsRoundingMode_WithCorrectRoundingMode_ShouldReturnCorrectRoundingMode(int oddsRoundingMode)
{
// Arrange
var oddsRoundingModeStr = oddsRoundingMode.ToString(); // <-- suggestion here
var mock = new Mock<IConstantsStorage>();
var oddsRoundingConfiguration = new OddsRoundingConfiguration(mock.Object);
mock.Setup(h => h.TryGetConstant(It.IsAny<string>(), It.IsAny<int>(), out oddsRoundingModeStr))
.Returns(true);
// Act
var roundingMode = oddsRoundingConfiguration.GetBaseOddsRoundingMode(0);
// Assert
Assert.AreNotEqual(roundingMode, OddsRoundingModes.None);
}
但是当我将此更改为未在声明时初始化时,模拟未正确设置且测试失败,因为oddsRoundingModeStr
未初始化且模拟将其返回为null。
为什么Resharper看不到这个?
编辑:
public bool TryGetConstant(string name, int siteId, out string value)
{
value = RetrieveConstant(_constantsModel, name, siteId);
return value != null;
}
private string RetrieveConstant<T>(IConstantsModel<T> model, string constName, int siteId)
where T : IConstant, new()
{
if (model.Constants.TryGetValue(constName, out List<T> values))
{
var constant = values.FirstOrDefault(v => v.Name == constName && v.SiteIds.Contains(siteId));
if (constant != null)
{
return constant.ConstantValue;
}
}
return null;
}
答案 0 :(得分:3)
遵循正常的C#语义,将该变量初始化为的值无关紧要,因为out
在为其分配新值之前无法读取数据。因此,resharper通知是合适的。
我看到使用此代码可以实现非标准语义的几种方法:
out
是CLR级别的装饰ref
。因此,低级代码可将其视为等同于ref
。
void Main()
{
Ref r = R;
Out o = (Out)Delegate.CreateDelegate(typeof(Out), null, r.Method);
int i = 2;
o(out i);
i.Dump();
}
delegate void Out(out int x);
delegate void Ref(ref int x);
void R(ref int x)
{
x++;
}
Setup
接受委托,然后对闭包对象使用私有反射。
Setup
使用Expression<T>
,即lambda的语法树,并以非标准方式解释表达式。
在此上下文中,lambda表达式不是要执行的C#代码,而是基本上描述如何设置模拟的DSL。
选项3似乎最有可能
答案 1 :(得分:2)
Setup
接受表达式树 - 并且Moq分析该表达式树以创建moq。在这种情况下,您基本上是说Moq应该创建IConstantsModel
的实现,它接受任何字符串,任何int,返回true并返回您在oddsRoundingModeStr
中提供的out
参数值。因此,在分析此表达式树时,Moq将提取oddsRoundingModeStr
的实际值(它被捕获并存储在编译器生成的类的字段中)并且实际上将使用它。 Resharper只是无法实现这一点,因此像往常一样提供警告。
如何从表达式树中提取out
变量值的小例子:
class Program {
static void Main(string[] args) {
int result = 2; // gives warning from your question
var back = ExtractOutValue(s => int.TryParse(s, out result));
Debug.Assert(back == result);
}
static int ExtractOutValue(Expression<Action<string>> exp) {
var call = (MethodCallExpression)exp.Body;
var arg = (MemberExpression) call.Arguments[1];
return (int) ((FieldInfo)arg.Member).GetValue(((ConstantExpression)arg.Expression).Value);
}
}