J'essaye de tester du code qui utilise une classe statique. La classe statique a une méthode d'initialisation qui ne peut être appelée qu'une seule fois et lève une exception si elle est appelée une deuxième fois. J'ai plusieurs cas de test qui testent le code qui doit accéder à la classe statique. Dans le code, l'initialisation se fait dans startup.cs. Comment faire quelque chose de similaire pour les cas de test. J'utilise x-unit pour les tests unitaires.
public string GenerateId { return UniqueId.NextId().ToString() }
Code que je souhaite tester:
public static class UniqueId { public static void Initialize() { if (_generator != null) throw new Exception("Already initialized."); _generator = new IdGenerator(); } private static IdGenerator _generator = null; public static BigId NextId() { if (_generator == null) throw new Exception("Not initialized."); return _generator.NextId(); } }
3 Réponses :
Dans votre cas spécifique, vous devez configurer votre classe pour implémenter l'IDisposable et appeler simplement Dispose () lorsque vous voulez le détruire.
Voici un exemple:
namespace Prime.UnitTests.Services { [TestFixture] public class YourClassTest { [SetUp] public void SetUp() { //some configs... } [Test] public void Test_size_String_1() { UniqueId.Initialize(); Assert.IsFalse(UniqueId.NextId().ToString() == 10); // quick example... UniqueId.Dispose(); } [Test] public void Test_size_String_2XPTO() { UniqueId.Initialize(); Assert.IsFalse(UniqueId.NextId().ToString() == 115); // quick example... UniqueId.Dispose(); } } } public static class UniqueId : IDisposable { public static void Initialize() { if (_generator != null) throw new Exception("Already initialized."); _generator = new IdGenerator(); } private static IdGenerator _generator = null; public static BigId NextId() { if (_generator == null) throw new Exception("Not initialized."); return c.NextId(); } public void Dispose() { _generator?.Dispose(); //Depends of the context of your IdGenerator //or _generator == null; } }
J'utilise X-Unit
IdGenerator est également une classe interne. Donc je ne peux pas me moquer directement de ça dans les cas de test
ici, suivez simplement ça, izi pizi :) docs. microsoft.com/en-us/dotnet/standard/garbage-collection/…
Je vais éditer ma solution pour que vous le testez :)
Alors, j'ai édité la solution.
Cela dépend du framework de test que vous utilisez.
EDIT: Je vois maintenant que vous utilisez xUnit, mais je laisserai la réponse entière au cas où cela serait utile à quelqu'un d'autre.
xUnitVous pouvez consulter cette réponse , qui parle de comment créer une configuration / démontage global pour un ensemble de tests. Pour résumer cette réponse, si vous créez un constructeur pour votre classe de test unitaire dans Xunit, cette méthode sera appelée avant chaque méthode de test. Il indique également:
Une version plus optimisée utiliserait l'interface IClassFixture pour assurez-vous que la fonctionnalité d'initialisation / de suppression globale est uniquement appelé une fois. Pour cette version, vous n'étendez pas une classe de base à partir de votre classe de test mais implémentez l'interface IClassFixture où T fait référence à votre classe d'appareil:
[TestFixture] public class MyTestFixture { [OneTimeSetUp] public void OneTimeSetUp() { // Initialize things here; only called once } }Cela entraînera l'exécution du constructeur de TestsFixture uniquement une fois pour chaque classe testée. Cela dépend donc de ce que vous voulez exactement pour choisir entre les deux méthodes.
Si vous utilisez NUnit , il possède déjà un attribut OneTimeSetUp
que vous pouvez utiliser ( docs ici ), comme ceci:
using Xunit; public class TestsFixture : IDisposable { public TestsFixture () { // Do "global" initialization here; Only called once. } public void Dispose() { // Do "global" teardown here; Only called once. } } public class DummyTests : IClassFixture<TestsFixture> { public DummyTests(TestsFixture data) { } }
Si vous ' si vous utilisez autre chose que xUnit et NUnit, consultez la documentation du framework que vous utilisez et recherchez une configuration unique.
En supposant que j'ai compris, dans MSTest
, regardez dans [TestInitialize]
, [ClassInitialize ]
(probablement ce dont vous avez besoin) et voyez si l'un ou l'autre fonctionne pour votre cas d'utilisation pour une fonction de "démarrage"
[TestInitialize
Classe ClassInitializeAttribute
Identifie une méthode qui contient du code qui doit être utilisé avant tout les tests de la classe de test ont été exécutés et pour allouer des ressources à utilisé par la classe de test. Cette classe ne peut pas être héritée.
Remarques
Lorsqu'elle est exécutée dans un test de charge, la méthode marquée avec cet attribut s'exécutera une fois, et toutes les opérations d'initialisation qu'il effectue s'appliquent à l'ensemble du test. Si vous devez effectuer des opérations d'initialisation une fois pour chaque itération d'utilisateur virtuel dans le test, utilisez le TestInitializeAttribute.
L'ordre dans lequel les méthodes seront exécutées est:
Méthodes marquées avec
AssemblyInitializeAttribute
.Méthodes marquées avec le
ClassInitializeAttribute
.Méthodes marquées du
TestInitializeAttribute
.Méthodes marquées du
TestMethodAttribute
.Une seule méthode dans une classe peut être décorée avec cet attribut.
Important
Cet attribut ne doit pas être utilisé sur les tests unitaires ASP.NET, c'est-à-dire test avec l'attribut [HostType ("ASP.NET")]. À cause des apatrides nature d'IIS et ASP.NET, une méthode décorée avec cet attribut peut être appelé plus d'une fois par test.
Hth
Quel cadre de test utilisez-vous?
J'utilise x-unit
Exécutez le code une fois avant et après TOUS les tests dans xUnit .net a une réponse intéressante, même si elle ne semble être disponible que dans les nouvelles versions de xUnit: stackoverflow.com/a/ 53143426/5803406
@devNull Cela a été utile. J'ai résolu mon problème. Merci beaucoup