在调试模式下运行单元测试时如何调用多个启动项目 [英] How do I invoke Multiple Startup Projects when running a unit tests in Debug Mode

查看:24
本文介绍了在调试模式下运行单元测试时如何调用多个启动项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎是一件简单的事情,但我似乎在任何地方都找不到任何信息!我有一个解决方案,其中包含我们在调试时以控制台模式"运行的服务.我希望在从 Visual Studio 运行单元测试时启动并附加"它.

This seems like a simple thing to do but I can't seem to find any info anywhere! I've got a solution that has a service that we run in 'Console Mode' when debugging. I want it to be started and 'attached' when I run my unit test from Visual Studio.

我使用 Resharper 作为单元测试运行器.

I'm using Resharper as the unit test runner.

推荐答案

不是直接回答你的问题,但是我们最近遇到了类似的问题,最终决定使用 AppDomain

Not a direct answer to your question, BUT We faced a similar problem recently and eventually settled on a solution using AppDomain

由于您的解决方案已经作为控制台项目运行,因此让它在新的 AppDomain 中启动几乎没有什么工作要做.此外,您可以在这个项目上运行断言以及单元测试的一部分.(如果需要)

As your solution is already running as a Console project it would be little work to make it boot in a new AppDomain. Furthermore, you could run Assertions on this project as well as part of unit testing. (if required)

考虑以下静态类 Sandbox,您可以使用它来启动多个应用程序域.Execute 方法需要一个类型,它是一个 SandboxAction.(类定义也包括在下面)

Consider the following static class Sandbox which you can use to boot multiple app domains. The Execute method requires a Type which is-a SandboxAction. (class definition also included below)

您将首先扩展这个类并提供用于运行您的控制台项目的任何启动操作.

You would first extend this class and provide any bootup actions for running your console project.

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

}

现在要运行您的应用程序域,您只需调用

Now to get your app domain running you simply call

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

请注意,您可以将此调用传递给一个配置文件,这样您就可以以与通过控制台运行项目相同的方式启动项目

Note you can pass this call a config file so you can bootup your project in the same fashion as if you were running it via the console

还有什么问题请追问.

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


}

这篇关于在调试模式下运行单元测试时如何调用多个启动项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆