Passer des parameters complexes à

Xunit a une fonctionnalité intéressante : vous pouvez créer un test avec un atsortingbut Theory et placer des données dans des atsortingbuts InlineData , et xUnit générera de nombreux tests et les testera tous.

Je veux avoir quelque chose comme ça, mais les parameters de ma méthode ne sont pas des «données simples» (comme ssortingng , int , double ), mais une liste de ma classe:

 public static void WriteReportsToMemoryStream( IEnumerable listReport, MemoryStream ms, StreamWriter writer) { ... } 

Il existe de nombreux atsortingbuts xxxxData dans XUnit. Découvrez par exemple l’atsortingbut PropertyData .

Vous pouvez implémenter une propriété qui renvoie IEnumerable . Chaque object[] généré par cette méthode sera ensuite «décompressé» en tant que paramètre pour un appel unique à votre méthode [Theory] .

Une autre option est ClassData , qui fonctionne de la même manière, mais permet de partager facilement les «générateurs» entre les tests dans différentes classes / espaces de noms, et sépare également les «générateurs de données» des méthodes de test réelles.

Voir ie ces exemples d’ici :

PropertyData Exemple

 public class SsortingngTests2 { [Theory, PropertyData(nameof(SplitCountData))] public void SplitCount(ssortingng input, int expectedCount) { var actualCount = input.Split(' ').Count(); Assert.Equal(expectedCount, actualCount); } public static IEnumerable SplitCountData { get { // Or this could read from a file. :) return new[] { new object[] { "xUnit", 1 }, new object[] { "is fun", 2 }, new object[] { "to test with", 3 } }; } } } 

Exemple ClassData

 public class SsortingngTests3 { [Theory, ClassData(typeof(IndexOfData))] public void IndexOf(ssortingng input, char letter, int expected) { var actual = input.IndexOf(letter); Assert.Equal(expected, actual); } } public class IndexOfData : IEnumerable { private readonly List _data = new List { new object[] { "hello world", 'w', 6 }, new object[] { "goodnight moon", 'w', -1 } }; public IEnumerator GetEnumerator() { return _data.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

Pour mettre à jour la réponse de @ Quetzalcoatl: L’atsortingbut [PropertyData] a été remplacé par [MemberData] qui prend comme argument le nom de chaîne de toute méthode statique, champ ou propriété IEnumerable un IEnumerable . (Je trouve particulièrement intéressant d’avoir une méthode itérative capable de calculer les cas de test un par un, en les générant au fur et à mesure qu’ils sont calculés.)

Chaque élément de la séquence retourné par l’énumérateur est un object[] et chaque tableau doit avoir la même longueur et cette longueur doit être le nombre d’arguments de votre test [MemberData] (annoté avec l’atsortingbut [MemberData] et chaque élément doit avoir le même tapez comme paramètre de méthode correspondant (ou peut-être peuvent-ils être des types convertibles, je ne sais pas.)

(Voir les notes de version pour xUnit.net mars 2014 et le correctif avec un exemple de code .)

La création de tableaux d’objects anonymes n’est pas la manière la plus simple de construire les données. J’ai donc utilisé ce modèle dans mon projet.

Définissez d’abord des classes partagées réutilisables

 //http://stackoverflow.com/questions/22093843 public interface ITheoryDatum { object[] ToParameterArray(); } public abstract class TheoryDatum : ITheoryDatum { public abstract object[] ToParameterArray(); public static ITheoryDatum Factory(TSystemUnderTest sut, TExecptedOutput expectedOutput, ssortingng description) { var datum= new TheoryDatum(); datum.SystemUnderTest = sut; datum.Description = description; datum.ExpectedOutput = expectedOutput; return datum; } } public class TheoryDatum : TheoryDatum { public TSystemUnderTest SystemUnderTest { get; set; } public ssortingng Description { get; set; } public TExecptedOutput ExpectedOutput { get; set; } public override object[] ToParameterArray() { var output = new object[3]; output[0] = SystemUnderTest; output[1] = ExpectedOutput; output[2] = Description; return output; } } 

Maintenant, vos tests individuels et vos données de membre sont plus faciles à écrire et à nettoyer …

 public class IngredientTests : TestBase { [Theory] [MemberData(nameof(IsValidData))] public void IsValid(Ingredient ingredient, ssortingng testDescription, bool expectedResult) { Assert.True(ingredient.IsValid == expectedResult, testDescription); } public static IEnumerable IsValidData { get { var food = new Food(); var quantity = new Quantity(); var data= new List(); data.Add(TheoryDatum.Factory(new Ingredient { Food = food } , false, "Quantity missing")); data.Add(TheoryDatum.Factory(new Ingredient { Quantity = quantity } , false, "Food missing")); data.Add(TheoryDatum.Factory(new Ingredient { Quantity = quantity, Food = food } , true, "Valid")); return data.ConvertAll(d => d.ToParameterArray()); } } } 

La propriété ssortingng Description de lancer un os lorsque l’un de vos nombreux cas de test échoue.

Vous pouvez essayer de cette façon:

 public class TestClass { bool isSaturday(DateTime dt) { ssortingng day = dt.DayOfWeek.ToSsortingng(); return (day == "Saturday"); } [Theory] [MemberData("IsSaturdayIndex", MemberType = typeof(TestCase))] public void test(int i) { // parse test case var input = TestCase.IsSaturdayTestCase[i]; DateTime dt = (DateTime)input[0]; bool expected = (bool)input[1]; // test bool result = isSaturday(dt); result.Should().Be(expected); } } 

Créez une autre classe pour contenir les données de test:

 public class TestCase { public static readonly List IsSaturdayTestCase = new List { new object[]{new DateTime(2016,1,23),true}, new object[]{new DateTime(2016,1,24),false} }; public static IEnumerable IsSaturdayIndex { get { List tmp = new List(); for (int i = 0; i < IsSaturdayTestCase.Count; i++) tmp.Add(new object[] { i }); return tmp; } } } 

Je suppose que vous vous êtes trompé ici. Ce que signifie réellement l’atsortingbut xUnit Theory : Vous voulez tester cette fonction en envoyant des valeurs spéciales / aléatoires en tant que parameters reçus par cette fonction. Cela signifie que ce que vous définissez comme atsortingbut suivant, tel que: InlineData , PropertyData , ClassData , etc. sera la source de ces parameters. Cela signifie que vous devez construire l’object source pour fournir ces parameters. Dans votre cas, je suppose que vous devriez utiliser l’object ClassData comme source. Notez également que ClassData hérite de: IEnumerable<> – cela signifie que chaque fois qu’un autre ensemble de parameters générés sera utilisé comme parameters entrants pour function-under-test jusqu’à ce que IEnumerable<> produise des valeurs.

Exemple ici: Tom DuPont .NET

L’exemple peut être incorrect – je n’ai pas utilisé xUnit pendant longtemps