【问题标题】:When class is instantiated by Unit Test, System.IO exception is triggered for image in instantiated class当单元测试实例化类时,实例化类中的图像会触发 System.IO 异常
【发布时间】:2019-05-16 19:51:08
【问题描述】:

我有一个可以正常工作的 Windows 窗体应用程序(编译会在 bin\debug 中创建 .exe 以及一个名为“Images”的文件夹。这个“Images”文件夹位于我的项目解决方案文件夹中,并设置为“始终复制”。

编译代码后,一切正常,没有 System.IO 异常。

但是,如果引用图像的类是在没有编译并通过单元测试工具的情况下实例化的,我会看到以下内容:

System.Drawing.Image.FromFile(字符串文件名,布尔值 useEmbeddedColorManagement) 在 System.Drawing.Image.FromFile(字符串文件名) 在 E:\workspaces\visual studio projects\Yahtzee\YahtzeeApplication\YahtzeeApplication\GameBoard.cs:line 124 中的 YahtzeeApplication.GameBoard..ctor() 在 E:\workspaces\visual studio projects\Yahtzee\YahtzeeApplication\UnitTestProject\GameBoardTest.cs:line 37 中的 UnitTestProject.GameBoardTest.GameBoardElements() 结果消息:System.IO.FileNotFoundException:Images\1.dice.GIF

这是加载图像的代码:

diceImageArray[0] = Image.FromFile("Images\\1.dice.GIF");

我正在查看测试类或实例化类是否没有看到图像。但是当我将一个名为“Images”的文件夹放在相对于调用的任一位置时,错误并没有消失。

你在单元测试中为这个场景做了什么?

【问题讨论】:

  • 我了解您可能花费了大量时间来研究并在嵌入文件和将它们分开之间进行选择,然后决定您采用的方法...但是由于您不太可能愿意模拟你的图像加载管理器我建议给嵌入图像一秒钟。
  • 您能发布尝试查找和加载图像的代码吗?是在您的测试代码中还是在您正在测试的系统中?
  • @Charlie - 我编辑了问题,所以代码现在在问题中,而不仅仅是我看到的异常。现在为了解决这个错误,我没有使用图像,而是改变了包含图像的图片框的颜色。同样,此代码在我编译和运行应用程序时都有效,因为 .exe 看到该文件夹​​并可以使用图像。但是,当我使用单元测试(未编译)实例化该类时,相对路径不正确。我相信这是问题所在。
  • 现在我没有使用图片。单元测试现在通过了。将设法让它们嵌入,而不是通过代码显示/查看。我现在遇到的问题是它不是一对一的。在图片框上放一张图片会很容易。我在其他表单上作为背景图像执行此操作,并且单元测试通过,因为没有 System.IO 异常。有问题的表单具有显示多个图像的图片框。
  • 您正在访问磁盘上的真实资源/图像。因此,这不是单元测试。这是一个集成测试。

标签: c# visual-studio unit-testing nunit


【解决方案1】:

相对路径不正确,因为您无法控制当前目录,这是相对路径所基于的。如果您只是运行控制台应用程序而不首先更改到包含图像目录的目录,则相同的代码也会失败,例如...

foo\bar\myprogram.exe

一般来说,程序的用户可以控制当前目录。程序更改当前目录或依赖于将其设置到任何特定位置是一种糟糕的形式……比如正在运行的程序集的位置。

查找图像目录的其他方法取决于路径是在您的测试中还是在被测应用程序中确定的。如果它在测试中,那么 NUnit 有TestContext.TestDirectory,这是包含测试程序集的目录的路径。如果它在应用程序本身中,则需要以某种方式对应用程序进行编码,以找到相对于某个特定位置的图像目录,例如包含主程序的目录。如果您指出此代码的位置,那么我可以给出更准确的建议。

更新 - 2019 年 1 月 22 日

在您的应用程序中使用相对路径是应用程序的一个弱点,这将导致它在某些情况下失败,除非您在程序运行时完全控制当前目录设置.在 NUnit 下运行测试只是其中一种情况。 IMO,您应该更改应用程序,以便它在相对于包含 exe 的目录的路径中找到图像,并且 not 相对于当前目录。这需要更多的代码,但更好,因为这实际上是您打算发生的事情。通过指出这个问题,您的测试对您有帮助!

这里有一些代码可以相对于加载图像的程序集的位置来定位图像(见下面的异常)...

string assemblyPath = GetType().Assembly.Location;
string assemblyDir = Path.GetDirectory(assemblyPath);
string imagePath = path.Combine(assemblyDir, "Images\\1.dice.GIF");
diceImageArray[0] = Image.FromFile(imagePath);

我将代码分布在多行中,以便您可以更轻松地查看每个步骤。当然,您可以组合其中的一些。该代码仅在 SO 中“编译”,因此我将留下任何错误供您修复。 :-)

上述代码的例外情况是您的代码正在被影子复制。然后,您需要访问它来自的原始位置,而不是当前位置。如果发生这种情况,则需要更多代码,我不想让示例过于复杂。

如果加载图像的程序集总是相对于自身定位它们,那么只要您确保图像存在于该位置,您的测试就应该有效。

【讨论】:

  • 测试类,就像在 selenium 中一样,只需要知道被测应用程序在哪里,这不是问题。我现在将对此进行更多研究,但现在我已经删除了图像并且应用程序现在只使用文本。它看起来不太好,但它可以工作并且我的测试通过了。
  • 这段代码 diceImageArray[0] = Image.FromFile("Images\\1.dice.GIF");住在我的应用程序中。文件夹/图像在编译时复制到输出文件夹。调试或运行 .exe 时,应用程序可以正常工作。如果我现在通过测试实例化具有图像的类,那么它会失败。这对我来说是有道理的,并且错误明确地说明了......被实例化的类与这些图像的相对路径错误。它(类)必须与图像处于/处于同一级别,而不是
  • 当您运行测试时,您的测试程序集相对于 exe 和 Images 目录位于何处?
  • 解决方案中有两个项目(UnitTest 和 Application)。测试从“UnitTest”项目运行并调用“Application”项目中的类。图像存在于“应用程序/图像”文件夹中。在应用程序中调用图像文件夹的类使用相对于应用程序的路径,因此当它编译时,它可以工作。当我从 UnitTest 项目调用应用程序时,该类是从它们的文件夹运行的,而不是作为 .exe 运行时的 bin/debug 文件夹。我明白为什么会这样,但就是无法正确获取文件夹
猜你喜欢
  • 1970-01-01
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2019-05-12
相关资源
最近更新 更多