C# Shouldly断言库如何知道该断言应用于的表达式?

C# Shouldly断言库如何知道该断言应用于的表达式?,c#,.net,shouldly,C#,.net,Shouldly,以某种方式知道调用断言方法的表达式,因此它能够将其显示在消息中。我试图找出它是如何工作的,但在源代码中迷失了方向。我怀疑它会查看编译后的代码,但我真的很想看看这是如何发生的。从文件中 map.IndexOfValue("boo").ShouldBe(2); // -> map.IndexOfValue("boo") should be 2 but was 1 不知何故,应该知道表达式map.IndexOfValue(“boo”),并且能够在测试失败消息中显示它。有人知道这是怎么发生的吗?

以某种方式知道调用断言方法的表达式,因此它能够将其显示在消息中。我试图找出它是如何工作的,但在源代码中迷失了方向。我怀疑它会查看编译后的代码,但我真的很想看看这是如何发生的。从文件中

map.IndexOfValue("boo").ShouldBe(2); // -> map.IndexOfValue("boo") should be 2 but was 1

不知何故,应该知道表达式map.IndexOfValue(“boo”),并且能够在测试失败消息中显示它。有人知道这是怎么发生的吗?

看看代码,这很聪明

魔法发生在
actualcodextgetter
类中。首先,它使用StackTrace检索源代码文件的行:

  StackTrace stackTrace = trace ?? new StackTrace(true);

  // Cut for brevity

  StackFrame stackFrame = frame;
  this.ShouldlyFrameIndex = index - 1;
  string fileName = stackFrame.GetFileName();
  this._determinedOriginatingFrame = fileName != null && File.Exists(fileName);
  this._shouldMethod = this.ShouldlyFrame.GetMethod().Name;
  this.FileName = fileName;
  this.LineNumber = stackFrame.GetFileLineNumber() - 1;
一旦有了源代码文件的名称以及语句的行和偏移量,就只需直接读取文件:

private string GetCodePart()
{
  string str = "Shouldly uses your source code to generate its great error messages, build your test project with full debug information to get better error messages\nThe provided expression";
  if (this._determinedOriginatingFrame)
  {
    string codeLines = string.Join("\n", ((IEnumerable<string>) File.ReadAllLines(this.FileName)).Skip<string>(this.LineNumber).ToArray<string>());
    int indexOfMethod = codeLines.IndexOf(this._shouldMethod);
    if (indexOfMethod > 0)
      str = codeLines.Substring(0, indexOfMethod - 1).Trim();
    str = !str.EndsWith("Should") ? str.RemoveVariableAssignment().RemoveBlock() : this.GetCodePartFromParameter(indexOfMethod, codeLines, str);
  }
  return str;
}
私有字符串GetCodePart()
{
string str=“Shouldly使用源代码生成大量错误消息,使用完整的调试信息构建测试项目以获得更好的错误消息\n提供的表达式”;
如果(这是确定的起始帧)
{
string codeLines=string.Join(“\n”,((IEnumerable)File.ReadAllLines(this.FileName)).Skip(this.LineNumber.ToArray());
int indexOfMethod=codeLines.IndexOf(this.\u shouldMethod);
如果(indexOfMethod>0)
str=codeLines.Substring(0,indexOfMethod-1).Trim();
str=!str.EndsWith(“应该”)?str.RemoveVariableAssignment().RemoveBlock():this.GetCodePartFromParameter(indexOfMethod,codeLines,str);
}
返回str;
}
有更多的逻辑来精确地隔离语句,但简言之,诀窍是:

  • 使用StackTrace检索源代码的位置和语句行
  • 解析源代码以检索准确的语句
当然,只有在编译代码所用的同一台机器上运行它时,它才能工作。

它会一直运行,直到找到一个不是Shouldly内部的方法,并将其名称视为被测试方法的名称