2016-06-18 31 views
4

Ich versuche, Setup-Code in einer meiner xUnit.net-Testklassen auszuführen, aber obwohl die Tests ausgeführt werden, scheint der Konstruktor nicht zu sein.xUnit.net: Test Klassenkonstruktoren nicht ausgeführt?

Hier einige meines Code:

public abstract class LeaseTests<T> 
{ 
    private static readonly object s_lock = new object(); 
    private static IEnumerable<T> s_sampleValues = Array.Empty<T>(); 

    private static void AssignToSampleValues(Func<IEnumerable<T>, IEnumerable<T>> func) 
    { 
     lock (s_lock) 
     { 
      s_sampleValues = func(s_sampleValues); 
     } 
    } 

    public LeaseTests() 
    { 
     AssignToSampleValues(s => s.Concat(CreateSampleValues())); 
    } 

    public static IEnumerable<object[]> SampleValues() 
    { 
     foreach (T value in s_sampleValues) 
     { 
      yield return new object[] { value }; 
     } 
    } 

    protected abstract IEnumerable<T> CreateSampleValues(); 
} 

// Specialize the test class for different types 
public class IntLeaseTests : LeaseTests<int> 
{ 
    protected override IEnumerable<int> CreateSampleValues() 
    { 
     yield return 3; 
     yield return 0; 
     yield return int.MaxValue; 
     yield return int.MinValue; 
    } 
} 

ich die SampleValues als MemberData verwenden, so kann ich sie in Tests wie diese

[Theory] 
[MemberData(nameof(SampleValues))] 
public void ItemShouldBeSameAsPassedInFromConstructor(T value) 
{ 
    var lease = CreateLease(value); 
    Assert.Equal(value, lease.Item); 
} 

jedoch nutzen, bin ich konsequent immer ein Fehler, der besagt, dass für [Methode] keine Daten gefunden wurden, für alle Methoden, die SampleValues verwenden. Nachdem ich weiter untersucht hatte, fand ich heraus, dass der LeaseTests Konstruktor nicht einmal ausgeführt wurde; Wenn ich beim Aufruf von AssignToSampleValues einen Haltepunkt gesetzt habe, wurde dieser nicht getroffen.

Warum passiert das und was kann ich tun, um es zu beheben? Vielen Dank.

Antwort

2

Der Konstruktor wird nicht ausgeführt, da MemberData vor dem Erstellen der Instanz der spezifischen Testklasse ausgewertet wird. Ich bin mir nicht sicher, ob dies Ihre Anforderungen erfüllen, aber Sie können folgendes tun:

definieren ISampleDataProvider Schnittstelle

public interface ISampleDataProvider<T> 
{ 
    IEnumerable<int> CreateSampleValues(); 
} 

typspezifische Implementierung hinzufügen:

public class IntSampleDataProvider : ISampleDataProvider<int> 
{ 
    public IEnumerable<int> CreateSampleValues() 
    { 
     yield return 3; 
     yield return 0; 
     yield return int.MaxValue; 
     yield return int.MinValue; 
    } 
} 

Resolve und Datenanbieter verwenden in SampleValues Methode

public abstract class LeaseTests<T> 
{ 
    public static IEnumerable<object[]> SampleValues() 
    { 
     var targetType = typeof (ISampleDataProvider<>).MakeGenericType(typeof (T)); 

     var sampleDataProviderType = Assembly.GetAssembly(typeof (ISampleDataProvider<>)) 
               .GetTypes() 
               .FirstOrDefault(t => t.IsClass && targetType.IsAssignableFrom(t)); 

     if (sampleDataProviderType == null) 
     { 
      throw new NotSupportedException(); 
     } 

     var sampleDataProvider = (ISampleDataProvider<T>)Activator.CreateInstance(sampleDataProviderType); 
     return sampleDataProvider.CreateSampleValues().Select(value => new object[] {value}); 
    } 
...