2009-07-13 23 views
5

J'essaie d'écrire un test unitaire C# avec le cadre de test unitaire intégré de VS 2008 et la méthode que je teste les appels Environment.Exit(0). Lorsque j'appelle cette méthode dans mon test unitaire, mon test d'unité est Aborted. La méthode devrait en effet appeler Exit, et je veux un moyen de tester ce qu'il fait, et aussi de tester le code de sortie qu'il utilise. Comment pourrais-je faire ça? J'ai regardé Microsoft.VisualStudio.TestTools.UnitTesting Namespace mais je n'ai rien vu de pertinent.Tests unitaires VS2008 - sortie de la méthode assert

[TestMethod] 
[DeploymentItem("myprog.exe")] 
public void MyProgTest() 
{ 
    // Want to ensure this Exit's with code 0: 
    MyProg_Accessor.myMethod(); 
} 

En attendant, voici l'essentiel du code que je veux tester:

static void myMethod() 
{ 
    Environment.Exit(0); 
} 

Edit: est la solution ici je dans ma méthode d'essai, grâce à RichardOD:

Process proc; 

try 
{ 
    proc = Process.Start(path, myArgs); 
} 
catch (System.ComponentModel.Win32Exception ex) 
{ 
    proc = null; 
    Assert.Fail(ex.Message); 
} 

Assert.IsNotNull(proc); 
proc.WaitForExit(10000); 
Assert.IsTrue(proc.HasExited); 
Assert.AreEqual(code, proc.ExitCode); 

Répondre

4

Cela semble être une très mauvaise idée. Environment.Exit (0), va évidemment faire comme prescrit, d'où la raison pour laquelle vos tests unitaires se brisent.

Si vous voulez vraiment continuer à tester cela, vous pouvez lancer un processus séparé et vérifier le code de retour - jetez un coup d'œil pour l'encapsuler dans Process.Start.

Je suppose qu'une autre option est de factoriser ce code et d'injecter un test spy, ou en utilisant un objet simulé pour vérifier le comportement correct.

Peut-être que vous pouvez faire quelque chose avec Typemock Isolator - Je crois que cela vous permet de mock static methods.

+0

+1 sur Typemock Isolateur ici - c'est la seule solution que je suis au courant de ce qui vous permet d'intercepter et moquez absolument rien. –

+0

Le danger de pouvoir se moquer des méthodes statiques est que vous ne vous détachez pas de les utiliser aussi facilement. En fait, je trouve que (pour mon code) être obligé de travailler très dur pour avoir des méthodes statiques est une bonne chose car je ne les utiliserai pas à moins qu'ils ne soient la meilleure solution absolue. Cela aide à forcer le développement en utilisant de meilleures techniques, IMO. L'inconvénient est que vous êtes obligé de sauter par des cerceaux lorsque vous interagissez avec ces méthodes statiques quand elles ont un sens (ou le cadre n'est pas construit avec des tests en tête). – tvanfosson

+0

@ tvanfosson- C'est un bon point. C'est pourquoi de nombreuses personnes (y compris moi-même) essaient d'éviter de trop utiliser les méthodes statiques lors de l'écriture de code testable. Les classes de framework .NET qui sont statiques sont un test de douleur et les développeurs doivent souvent recourir à l'écriture de code wrapper pour le rendre testable (selon votre réponse). Vous pouvez voir cela beaucoup de l'évolution des formulaires Web ASP.NET à ASP.NET MVC. – RichardOD

3

Vous ne serez pas en mesure de tester cela - Environment.Exit tue complètement l'application. Cela signifie que tout AppDomain qui utilise ce code sera complètement déchargé, que ce soit votre application de production ou le framework de test unitaire.

2

Votre seule option ici serait de simuler la classe d'environnement avec une méthode de sortie fakie.

5

Vous devrez créer un wrapper pour la classe Environment, puis utiliser le wrapper dans votre code. Pour vos tests unitaires, injectez une version fictive du wrapper. L'exemple suivant utilise RhinoMocks pour vérifier que la méthode appelle le wrapper avec l'argument attendu.

public class EnvironmentWrapper 
{ 
    public virtual void Exit(int code) 
    { 
     Environment.Exit(code); 
    } 
} 


public class MyClass 
{ 
    private EnvironmentWrapper Environment { get; set; } 

    public MyClass() : this(null) { } 

    public MyClass(EnvironmentWrapper wrapper) 
    { 
     this.Environment = wrapper ?? new EnvironmentWrapper(); 
    } 

    public void MyMethod(int code) 
    { 
     this.Environment.Exit(code) 
    } 
} 


[TestMethod] 
public void MyMethodTest() 
{ 
    var mockWrapper = MockRepository.GenerateMock<EnvironmentWrapper>(); 

    int expectedCode = 5; 

    mockWrapper.Expect(m => m.Exit(expectedCode)); 

    var myClass = new MyClass(mockWrapper); 

    myclass.MyMethod(expectedCode); 

    mockWrapper.VerifyAllExpectations() 
} 
+1

+1. Bel exemple, si je ne mangeais pas mon dîner j'allais coder quelque chose dans ce sens! Votre code me rappelle le code par défaut dans la classe AccountController des projets ASP.NET MVC, ce qui peut être une bonne chose. Personnellement, je voudrais changer EnvironmentWrapper Environnement public {get; ensemble; } à un ensemble privé, mais en dehors de ce bel exemple. – RichardOD

+0

@RichardOD - convenu sur le public/privé. Mettra à jour. – tvanfosson

0

Vous pouvez ajouter un argument à votre méthode pour lui transmettre un faux environnement dans lequel la méthode exit() ne se fermera pas.

Vous pouvez extraire cette méthode paramétrée de la méthode appelée depuis votre application et tester la fonction extraite. De cette façon, vous n'aurez pas à modifier votre application.

0

La seule chose qui me vient à l'esprit est quelque chose le long:

static void myMethod() 
{ 
    DoEnvironmentExit(0); 
} 

static void DoEnvironentExit(int code) 
{ 
    #if defined TEST_SOLUTION 
     SomeMockingFunction(code); 
    #else 
     Environment.Exit(code); 
    #endif 
}