开发者

How do I invoke Multiple Startup Projects when running a unit tests in Debug Mode

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.

I'm using Resharper as the unit test runner.


Not a direct answer to your question, BUT We faced a similar problem recently and eventually settled on a solution using 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)

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

Any more questions please ask.

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


}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜