Вопрос: Как сделать нативную библиотеку доступной для NUnit при запуске тестов, чтобы ее можно было загружать при запуске?
Фон: Недавно я начал использовать NUnit для тестов, и я изо всех сил пытаюсь настроить тест, который включает неуправляемую (нативную) библиотеку (назовем ее x.dll
). Проект, который я тестирую, управляется оболочкой c ++ / CLI вокруг этой библиотеки. У меня есть тестовый проект NUnit c #, который ссылается на оболочку, поэтому я могу использовать функции, определенные там. Проблема в том, что когда я запускаю тест, System.IO.FileNotFoundException
брошен, указывая, что x.dll
не может быть найден Мне нужно как-то указать NUnit на его местоположение, или заставить его скопировать dll в каталог выполнения (который спрятан где-то в temp
каталог), но не смог найти, как это сделать после довольно обширного поиска — вероятно, пропустил правильные ключевые слова.
Я использую расширение NUnit 3 в Visual Studio, и тестовый проект был создан с использованием шаблона, также доступного в качестве расширения.
Хитрость в использовании неуправляемых сборок заключается в том, чтобы знать, что они обнаруживаются операционной системой с использованием подхода, отличного от способа, которым .NET находит управляемые ссылки.
В качестве обновления: неуправляемые сборки находятся по пути, в то время как управляемые сборки находятся в AppBase или в приватном binpath под ним.
Я предполагаю, что это VS копирует x.dll
в выходной каталог. Если нет, вы должны сделать это, установив для CopyLocal значение true. Теперь, прежде чем запускать тест, добавьте этот каталог в начало вашего пути. Если вы еще не используете скрипт, вам, вероятно, придется создать его, чтобы сделать это.
Поскольку я хотел, чтобы тесты были автономными и могли запускаться с использованием таких инструментов, как Resharper или Visual Studio Test Framework (с использованием расширения NUnit), я старался избегать запуска тестов из сценариев, как предложил @Charlie, потому что я не знал, как интегрировать результаты с этими инструментами.
Однако мне удалось найти интересный атрибут OneTimeSetUpAttribute
, который может быть использован для обозначения функции так, чтобы он будет проходить каждый раз перед тестами. К счастью, это реализовано в том же процессе, в котором выполняются тесты, поэтому мы можем использовать это для элегантного изменения переменной Path. Это код, который я использую для изменения Path, который также позволяет различать архитектуру, на которой они работают:
void RegisterLibs()
{
const string pathVar = "Path";
const string fileUriTag = "file:///";
// Get executable path
var exePath = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
if (exePath.StartsWith(fileUriTag))
exePath = exePath.Remove(0, fileUriTag.Length);
// Extract directory
var exeDir = System.IO.Path.GetDirectoryName(exePath);
// Get path variable
var pathVal = Environment.GetEnvironmentVariable(pathVar) ?? "";
// Simple check for architecture.
// 4-byte pointer => 32bit
// 8-byte pointer => 64bit
var arch = IntPtr.Size == 4 ? "Win32" : "x64";
// Prepare new entry for path
var libPath = $"{exeDir}\\{arch};";
if (pathVal.Contains(libPath))
return;
// Prepend the entry
pathVal = pathVal.Insert(0, libPath);
// Update path variable
Environment.SetEnvironmentVariable(pathVar, pathVal);
}
которые затем могут быть использованы в тестах:
[TestFixture]
public class UnitTests
{
[OneTimeSetUpAttribute]
public void TestFixtureSetup()
{
RegisterLibs();
}
[Test]
public void Test1()
{
// Path is set-up here
// ...Your test code...
}
}