Подтвердить что ты не робот

Как я могу использовать отдельный AppDomain для каждого метода тестирования xUnit.net?

xUnit использует те же AppDomain для всей тестовой сборки, это проблематично, поскольку я тестирую библиотеку пользовательского интерфейса и вам нужно создать новый экземпляр Application для каждого отдельного теста.

Это работает, когда я запускаю один тест, но когда я Run All прошел первый тест, но все последующие тесты терпят неудачу с Cannot create more than one System.Windows.Application instance in the same AppDomain в строке, где я создаю новый объект Application.

4b9b3361

Ответ 1

Возможно, вы могли бы попробовать сделать свой тест class следующим образом:

public class DomainIsolatedTests : IDisposable
{
  private static int index = 0;
  private readonly AppDomain testDomain;

  public DomainIsolatedTests()
  {
    var name= string.Concat("TestDomain #", ++index);
    testDomain = AppDomain.CreateDomain(name, AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
    // Trace.WriteLine(string.Format("[{0}] Created.", testDomain.FriendlyName)); 
  }

  public void Dispose()
  {
    if (testDomain != null)
    {        
      // Trace.WriteLine(string.Format("[{0}] Unloading.", testDomain.FriendlyName));
      AppDomain.Unload(testDomain);        
    }
  }

  [Fact]
  public void Test1()
  {
    testDomain.DoCallBack(() => {
      var app = new System.Windows.Application();

      ...
      // assert
    });
  }

  [Fact]
  public void Test2()
  {
    testDomain.DoCallBack(() => { 
      var app = new System.Windows.Application();

      ...
      // assert
    });
  }

  [Fact]
  public void Test3()
  {
    testDomain.DoCallBack(() => {
      var app = new System.Windows.Application();

      ...
      // assert
    });
  }

  ...
}

Ответ 2

Возможно, foreach Test вы можете динамически загружать свою сборку в новый домен.

public static void DynamicExecution(String assemblyFileName, String uniqueDomName)
{
    Boolean retVal = false;

        AppDomain newDomain = AppDomain.CreateDomain(uniqueDomName);
        YourClass yourClass = (YourClass)newDomain.CreateInstanceFromAndUnwrap(assemblyFileName, "YourClass");

        //do what you need with yourClass Object


        AppDomain.Unload(newDomain);
        newDomain = null;
}

Ответ 3

AppDomain appDomain = AppDomain.CreateDomain("WorkerDomain " + Thread.CurrentThread.Name);

var domain = (AppDomainWorker)appDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(AppDomainWorker).FullName);

domain.Executor();

internal class AppDomainWorker
{
    internal object Executor ()
    {
        // your unit test can run here
    }
}

Еще две важные вещи:

1) Возможно, вам нужно будет пометить класс как MarshalByRefObject и переопределить метод InitializeLifetimeService, чтобы объект был более продолжительным или существовал. MarshalByRefObject потребуется, если вам нужно общаться между доменами приложения. Подробнее об этом читайте в концепции Microsoft Remoting.

2) Иногда нам понадобится разрешение сборки в AppDomains, если оно не принимает сборки, загруженные в родительский домен, но это очень редко.