xUnit 控制台运行程序生成的 XML 结果文件也有类似的情况。我在这里添加它作为答案,以防它帮助其他人在 StreamReader 采用 XmlTextReader 的形式时找到原因/解决方案,它构建在 Stream 和 TextReader 之上,并且还可以在底层文件上放置锁如果底层流和读取器在读取完成后未关闭并立即处理,则使后续的移动和删除操作失败。
public void ReadResultsXmlFile(string testResultsXmlFile)
{
MyXmlTextReader = new XmlTextReader(testResultsXmlFile);
testResultXmlDocument = new XmlDocument();
testResultXmlDocument.Load(MyXmlTextReader);
XmlNode xnAssembliesHeader = testResultXmlDocument.SelectSingleNode("/assemblies");
XmlNodeList xnAssemblyList = testResultXmlDocument.SelectNodes("/assemblies/assembly");
foreach (XmlNode assembly in xnAssemblyList)
{
XmlNodeList xnTestList = testResultXmlDocument.SelectNodes(
"/assemblies/assembly/collection/test");
foreach (XmlNode test in xnTestList)
{
TestName = test.Attributes.GetNamedItem("name").Value;
TestDuration = test.Attributes.GetNamedItem("time").Value;
PassOrFail = test.Attributes.GetNamedItem("result").Value;
}
}
}
当然,事后看来,很明显我未能关闭包含底层 StreamReader 的 XmlTextReader,这会在 XML 结果文件上留下锁。
固定代码如下所示:
public void ReadResultsXmlFile(string testResultsXmlFile)
{
using (MyXmlTextReader = new XmlTextReader(testResultsXmlFile))
{
testResultXmlDocument = new XmlDocument();
testResultXmlDocument.Load(MyXmlTextReader); // suppose that myXmlString contains "<Names>...</Names>"
XmlNode xnAssembliesHeader = testResultXmlDocument.SelectSingleNode("/assemblies");
XmlNodeList xnAssemblyList = testResultXmlDocument.SelectNodes("/assemblies/assembly");
foreach (XmlNode assembly in xnAssemblyList)
{
XmlNodeList xnTestList = testResultXmlDocument.SelectNodes(
"/assemblies/assembly/collection/test");
foreach (XmlNode test in xnTestList)
{
TestName = test.Attributes.GetNamedItem("name").Value;
TestDuration = test.Attributes.GetNamedItem("time").Value;
PassOrFail = test.Attributes.GetNamedItem("result").Value;
}
}
}
}
...并且后续移动和删除操作的锁定文件问题消失了。当然,关键线是
using (MyXmlTextReader = new XmlTextReader(testResultsXmlFile))
{
// Do stuff inside "using... block
} // At close of "using" block, objects in using get Released...
值得一提的是,该应用程序是一个测试运行程序,它运行基于 Selenium 的自动化 Web 测试,使用 xUnit 控制台测试运行程序,并通过命令行选项告诉 xUnit 控制台运行程序创建 XML 结果文件。在 xUnit 测试运行器层之上还涉及 SpecFlow,但正在读取 xUnit 结果文件。在测试执行之后,我想将 XML 结果文件移动到基于日期的存档文件夹中,并且由于 xUnit 结果文件上的锁定,File.Move() 操作失败,这是由于代码没有使用块。