Resharper запускает UnitTest из другого места

Когда я запускаю модульные тесты с Visual Studio, он работает нормально, потому что он запускается из каталога проекта, где находятся все сборки. Но когда я запускаю его с Resharper, он идет с ошибкой на

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

с ошибкой

Не удалось загрузить файл или сборку SomeAssembly или одну из ее зависимостей. Система не может найти указанный файл..

Итак, я попробовал

var path = Assembly.GetExecutingAssembly().Location;

и это не проект один. Это

C:\Users\*UserName*\AppData\Local\Temp\TestResults\...\Out\

и нет "SomeAssembly". Как правильно настроить resharper или собрать все сборки, как это делает Visual Studio?

Это происходит с юнит-тестами, но не с NUnit, есть идеи?

10 ответов

Решение

Resharper теневые копии сборок для тестирования по умолчанию. Если вы отключите теневое копирование, оно будет запущено в папке bin, и тест должен пройти. Вот несколько инструкций по его выключению.

В документации по настройкам NUnit's Gui Test Runner есть следующее примечание о 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;
    }

У меня возникла та же проблема, программа-тестировщик resharper была в C:\, тогда как фактически собранные dll и решение были на другом диске. Решение состояло в том, чтобы убрать галочку "Использовать Legacy Runner" на странице настроек MSTest в опциях перекомпоновки.

Попробуйте создать файл testsettings и настроить правила развертывания для ваших тестов.

В старых версиях resharper, похоже, есть некоторые ошибки при обработке развертывания папок, я думаю, что это исправлено в последней версии resharper 7.

Попробуйте этот код для загрузки (см. Ниже). Это будет искать сборки независимо от тестового бегуна.

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 )
}

Вы загружаете свои сборки динамически, используя Assembly.Load(), Возможно, вам не хватает ссылки на сборку для загрузки. В противном случае теневое копирование может пропустить несвязанные сборки.

Если вы не хотите ссылаться на эти сборки, обязательно включите их в свой проект и скопируйте их в выходной каталог. Это можно сделать, установив свойство "Копировать в выходной каталог" или создав пользовательский шаг после сборки.

Просто чтобы завершить очень полезный ответ от mcdon, с помощью assembly.Location дает правильный ответ в соответствии с объяснением MSFT:

CodeBase - это URL-адрес места, где был найден файл, а Location - это путь, с которого он был фактически загружен. Например, если сборка была загружена из Интернета, ее CodeBase может начинаться с "http://", а ее местоположение может начинаться с "C:\". Если файл был скопирован теневым копированием, в качестве местоположения будет указан путь к копии файла в каталоге теневого копирования.

Также полезно знать, что CodeBase не гарантированно будет установлен для сборок в GAC. Однако для всегда загружаемых с диска сборок всегда будет указано местоположение.

Поэтому я бы использовал следующее:

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

Просто измените текущий каталог

var dir = Path.GetDirectoryName(typeof(MySetUpClass).Assembly.Location);
Environment.CurrentDirectory = dir;

// or
Directory.SetCurrentDirectory(dir);

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

Если у вас возникли проблемы с запуском и сборкой после отключения "теневой сборки", вы должны сначала выбрать "Очистить все" из опции "Сборка", а после этого построить свой проект при "теневой сборке" отключить.

Для меня это решило установить для свойства "Копировать локальное" значение true для ссылки nunit.framework.dll в тестовом проекте.

Другие вопросы по тегам