Resharper从不同的位置运行单元测试

49

在使用Visual Studio运行单元测试时,一切都很正常,因为它从包含所有程序集的项目目录中运行。 但是当我使用resharper运行测试时,会出现错误。

var services = Assembly.Load("SomeAssembly");

出现错误

无法加载文件或程序集“SomeAssembly”或其某个依赖项。系统找不到指定的文件。

所以我尝试过

var path = Assembly.GetExecutingAssembly().Location;

而且这不是第一个项目。它是:

C:\Users\*用户名称*\AppData\Local\Temp\TestResults\...\Out\

并且没有'SomeAssembly'。我该如何正确地配置resharper或者像Visual Studio一样收集所有的程序集?

这会发生在单元测试中,但不会出现在NUnit中,有任何想法吗?

10个回答

44

Resharper默认会为测试创建影像拷贝程序集。如果您关闭了影像拷贝,它将在bin文件夹中运行,测试应该会通过。这里提供了一些关闭影像拷贝的指令。


这种情况发生在单元测试中,但不会出现在 NUnit 中,那么有什么区别,有什么想法吗?@tallseth - Roar
当你说“单元测试,但不使用nunit”时,你是指MSTest吗?还是你的意思是它可以使用nunit控制台运行器,但不能使用resharper插件,并且所有测试都使用nunit框架? - tallseth
1
是的,当我使用Resharper运行MSTest时会失败,但是当我使用TestExplorer运行MSTest时它可以正常运行,而且当我使用Resharper运行NUnit时也能够正常运行。 - Roar
我已经禁用了影子复制,但仍然存在相同的问题。如果我从测试资源管理器中运行它,它可以工作,但是通过Resharper就不行。 - Remy
所以,如果它是一个nunit测试,在所有情况下都可以正常运行,而mstests则不行?停止使用mstext,转换为nunit。这里有一个指南:http://knot.org/scottlaw/blog/?p=404 - tallseth
另一个想法可能是尝试更新R#,因为我遇到了类似的问题,即“影子复制”无法解决它。这是一个版本错误。 - Alex M

26
在 NUnit 的 Gui 测试运行器设置的 documentation 中,有关 Shadow Copy 的注释如下:

注意:如果您想禁用影像复制以便访问与您的程序集相同目录中的文件,您应该知道还有其他选择。考虑使用 Assembly.Codebase 属性而不是 Assembly.Location。

下面是使用 Assembly.Codebase 属性的示例。
    private string AssemblyLocation()
    {
        var assembly = Assembly.GetExecutingAssembly();
        var codebase = new Uri(assembly.CodeBase);
        var path = codebase.LocalPath;
        return path;
    }

9
我现在正在使用NUnit 3.0,并发现了TestContext.CurrentContext.TestDirectory。我不知道TestContext.CurrentContext.TestDirectory是从哪个版本开始提供的。请帮我翻译这段内容,确保在不改变原意的情况下使其更加通俗易懂。 - mcdon
你应该将TestContext解决方案作为另一个答案添加,因为它本身就是一个很好的答案。我会投票支持它。 这在NUnit 2.6中也有效,并且我认为对于2.x版本来说都是如此。 - Holf

12

我曾遇到同样的问题,Resharper测试运行器位于C:\,而实际构建的dll和解决方案位于另一个驱动器。 解决办法是在Resharper选项中的MSTest设置页面中取消选中“使用传统的运行器”。


3
尝试使用以下代码来加载(请见下文)。它将查找与测试运行程序无关的程序集。
private static string[] assemblyLookupPath = new[]
{
    AppDomain.CurrentDomain.BaseDirectory, 
    Environment.CurrentDirectory,
    Assembly.GetExecutingAssembly().Location
}.Distinct().ToArray();

public static void Assembly Load(string fileName)
{
     var filePath = assemblyLookupPath
         .Select(f=>Path.Combine(f, fileName))
         .Where(File.Exists)
         .FirstOrDefault();

     /*do here null checks and raise errors, write logs, etc*/

     return Assembly.LoadFrom(filePath )
}

3

遗憾的是,使用Resharper 7.1.3和VS 2012仍无法解决此问题。 - Daniel Bişar

2

补充一下mcdon非常有帮助的回答,根据微软的解释,使用assembly.Location可以得到正确的结果:

CodeBase是文件被找到的URL,而Location是从实际加载的路径。例如,如果程序集是从互联网下载的,则它的CodeBase可能以“http://”开头,但其Location可能以“C:\”开头。如果文件是影子复制的,则Location将是影子复制目录中文件的路径。

需要知道的是,GAC中的程序集不能保证设置CodeBase。但是,从磁盘加载的程序集Location始终会被设置。

因此,建议使用以下代码:

public static DirectoryInfo GetAssemblyDirectory()
{
    var assembly = Assembly.GetExecutingAssembly();    
    return new DirectoryInfo(Path.GetDirectoryName(assembly.Location));
}

2
你正在使用 Assembly.Load() 动态加载程序集。可能你缺少要加载的程序集的引用。否则,影子复制可能会漏掉未被引用的程序集。
如果你不想引用这些程序集,请确保将它们包含在你的项目中并将它们复制到输出目录中。你可以通过设置 "复制到输出目录" 属性或创建自定义后构建步骤来实现。

我引用了所需的程序集,在 NUnit 测试中可以正常工作,但在默认的 Visual Studio 测试 Microsoft.VisualStudio.TestTools.UnitTesting 中无法工作。 - Roar
目前还没有想法。顺便说一下,Microsoft.VisualStudio.TestTools.UnitTesting功能通常被称为“MSTest”。也许这有助于获得更好的搜索结果。 - Dio F

1
只需更改当前目录。
var dir = Path.GetDirectoryName(typeof(MySetUpClass).Assembly.Location);
Environment.CurrentDirectory = dir;

// or
Directory.SetCurrentDirectory(dir);

https://github.com/nunit/nunit/issues/1072


0
我的解决方法是在测试项目中将nunit.framework.dll的“Copy Local”属性设置为true。

0

如果你在禁用“影子构建”后遇到了运行和构建问题,你必须首先从构建选项中选择“清除所有”,然后再在禁用“影子构建”后构建你的项目。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接