2014-01-20 7 views
13

xUnit은 전체 테스트 어셈블리에 대해 동일한 AppDomain을 사용합니다. 이는 UI 라이브러리를 테스트하고 각 개별 테스트에 대해 새로운 Application 인스턴스를 만들어야하므로 문제가됩니다.각 xUnit.net 테스트 방법에 대해 별도의 AppDomain을 어떻게 사용할 수 있습니까?

단일 테스트를 실행할 때 작동하지만 Run All 첫 번째 테스트가 통과되었지만 모든 후속 테스트가 Application 개체를 만드는 라인에서 Cannot create more than one System.Windows.Application instance in the same AppDomain으로 실패합니다.

+0

각 테스트 (예 : 테스트 방법) 또는 각 텍스트 "조명기" –

+2

@PeterRitchie 각 테스트 방법 (사실) – Flagbug

+2

http://patrick.lioi.net/2013/04/18/isolating-execution/ –

답변

5

아마 당신은이 같은 테스트 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

흠,이 "작동"하지만 문제는 DoCallBack 메서드에서 테스트가 실패하더라도 xUnit 테스트가 성공했다고보고합니다. 예외가 어떻게 든 삼킨 것 같아 – Flagbug

+0

@Flagbug 당신은 _failing_ 테스트의 예제를 줄 수 있습니까? – IronGeek

+0

@Flugbug xUnit에서 예외를 전파 할 수 있도록 예외를 전파 했습니까? – khorvat

0

어쩌면, foreach는 테스트 동적으로 새 도메인에 어셈블리를로드 할 수 있습니다.

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; 
} 
0
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 메소드를 오버라이드 (override) 할 필요가 있습니다 . MarshalByRefObject은 appdomain간에 통신해야하는 경우에 필요합니다. 이에 대한 자세한 내용은 Microsoft 원격 개념을 참조하십시오.

2) 때로는 부모 도메인에로드 된 어셈블리를 사용하지 않지만 매우 드물지만 AppDomains에서 어셈블리를 확인해야 할 수도 있습니다.