Как вызвать несколько проектов запуска при запуске модульных тестов в режиме отладки - PullRequest
2 голосов
/ 14 февраля 2011

Это кажется простым делом, но я нигде не могу найти информацию!У меня есть решение, которое имеет сервис, который мы запускаем в «Консольном режиме» при отладке.Я хочу, чтобы он запускался и «подключался», когда я запускаю свой модульный тест из Visual Studio.

Я использую Resharper в качестве устройства для выполнения юнит-теста.

1 Ответ

1 голос
/ 15 февраля 2011

Не прямой ответ на ваш вопрос, НО Мы недавно столкнулись с подобной проблемой и в итоге остановились на решении с использованием AppDomain

Поскольку ваше решение уже запущено как консольный проект, было бы немного работызагрузите его в новом домене приложений.Кроме того, вы можете запустить Assertions для этого проекта, а также часть модульного тестирования.(если требуется)

Рассмотрим следующий статический класс Sandbox, который можно использовать для загрузки нескольких доменов приложений.Для метода Execute требуется тип, который является SandboxAction.(определение класса также включено ниже)

Сначала вы должны расширить этот класс и предоставить любые действия по загрузке для запуска вашего консольного проекта.

public class ConsoleRunnerProjectSandbox : SandboxAction
{
  protected override void OnRun()
    {
         Bootstrapper.Start(); //this code will be run on the newly create app domain
    }

}

Теперь, чтобы получить ваше приложениедомен, на котором вы работаете, просто позвоните

Sandbox.Execute<ConsoleRunnerProjectSandbox>("AppDomainName", configFile)

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

Пожалуйста, задавайте еще вопросы.

public static class Sandbox
{
    private static readonly List<Tuple<AppDomain, SandboxAction>> _sandboxes = new List<Tuple<AppDomain, SandboxAction>>();

    public static T Execute<T>(string friendlyName, string configFile, params object[] args)
        where T : SandboxAction
    {
        Trace.WriteLine(string.Format("Sandboxing {0}: {1}", typeof (T).Name, configFile));

        AppDomain sandbox = CreateDomain(friendlyName, configFile);

        var objectHandle = sandbox.CreateInstance(typeof(T).Assembly.FullName, typeof(T).FullName, true, BindingFlags.Default, null, args, null, null, null);

        T sandBoxAction = objectHandle.Unwrap() as T;

        sandBoxAction.Run();


        Tuple<AppDomain, SandboxAction> box = new Tuple<AppDomain, SandboxAction>(sandbox, sandBoxAction);
        _sandboxes.Add(box);

        return sandBoxAction;
    }

    private static AppDomain CreateDomain(string name, string customConfigFile)
    {
        FileInfo info = customConfigFile != null ? new FileInfo(customConfigFile) : null;
        if (!string.IsNullOrEmpty(customConfigFile) && !info.Exists)
            throw new ArgumentException("customConfigFile not found using " + customConfigFile + " at " + info.FullName);

        var appsetup = new AppDomainSetup();
        //appsetup.ApplicationBase = Path.GetDirectoryName(typeof(Sandbox).Assembly.Location);
        appsetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
        if (customConfigFile==null)
            customConfigFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
        appsetup.ConfigurationFile = customConfigFile;

        var sandbox = AppDomain.CreateDomain(
            name,
            AppDomain.CurrentDomain.Evidence,
            appsetup);
        return sandbox;
    }

    public static void DestroyAppDomainForSandbox(SandboxAction action)
    {
        foreach(var tuple in _sandboxes)
        {
            if(tuple.Second == action)
            {
                AppDomain.Unload(tuple.First);
                Console.WriteLine("Unloaded sandbox ");
                _sandboxes.Remove(tuple);
                return;
            }
        }
    }
}


 [Serializable]
public abstract class SandboxAction : MarshalByRefObject
{
    public override object InitializeLifetimeService()
    {
        return null;
    }
    public void Run()
    {
        string name = AppDomain.CurrentDomain.FriendlyName;
        Log.Info("Executing {0} in AppDomain:{1} thread:{2}", name, AppDomain.CurrentDomain.Id, Thread.CurrentThread.ManagedThreadId);

        try
        {
            OnRun();
        }
        catch (Exception ex)
        {
            Log.Error(ex, "Exception in app domain {0}", name);
            throw;
        }
    }

    protected abstract void OnRun();

    public virtual void Stop()
    {
    }


}
...