2010-07-15 6 views
5

Je commence à utiliser le framework Moq et je l'adore. J'écris quelques tests de contrôleur qui ont plusieurs services et interfaces pour organiser mon contrôleur pour le test. J'adorerais le modulariser un peu plus, et je pensais que ce serait une tâche triviale, mais il s'avère que c'est un peu plus compliqué que je ne le pensais.Test du contrôleur Moq avec configuration répétée

Voici un simple test de l'unité que je dois montrer un exemple:

[Test] 
public void Get_SignIn_Should_Return_View() 
{ 
    #region //TODO: figure out how to extract this out to avoid duplicate code 
    // Arrange 
    var membershipService = new Mock<IMembershipService>(); 
    var formsService = new Mock<IFormsAuthenticationService>(); 
    var userService = new Mock<IUserService>(); 
    var dictService = new Mock<IDictionaryService>(); 
    var shoppingBasketService = new Mock<IShoppingBasketService>(); 

    //Create the service provider mock and pass in the IRepositoryFactory so that it isn't instantiating real repositories 
    var repoFactory = new Mock<IRepositoryFactory>(); 
    var serviceProvider = new Mock<ServiceProvider>((IRepositoryFactory)repoFactory.Object); 

    var context = new Mock<HttpContextBase> { DefaultValue = DefaultValue.Mock }; 
    var sessionVars = new Mock<SessionVars>(); 

    AccountController controller = new AccountController(serviceProvider.Object, sessionVars.Object) 
    { 
     FormsService = formsService.Object, 
     MembershipService = membershipService.Object, 
     UserService = userService.Object, 
     DictionaryService = dictService.Object, 
     ShoppingService = shoppingBasketService.Object 
    }; 
    controller.ControllerContext = new ControllerContext() 
    { 
     Controller = controller, 
     RequestContext = new RequestContext(context.Object, new RouteData()) 
    }; 
    #endregion 

    // Act 
    ActionResult result = controller.SignIn(); 

    // Assert 
    Assert.IsInstanceOf<ViewResult>(result); 
} 

Ce que je voudrais être en mesure de faire est de prendre tout le #region et extraire que sortir dans une méthode d'assistance ou [Setup] méthode, mais si je fais cela, alors je n'ai pas accès à chaque service fictif pour configurer les attentes.

Y at-il quelque chose qui me manque ici, ou dois-je vraiment copier et coller ce morceau de code d'arrangement dans chaque test d'unité?

Répondre

3

Mettez les tests à l'intérieur de ces appareils et violà! Ce code peut ne pas être parfait pour le framework que vous utilisez. Si c'est NUnit, ce sera le cas. Mais la théorie est là.

public abstract class MembershipTestContext 
    { 
     var membershipService = new Mock<IMembershipService>(); 
     var formsService = new Mock<IFormsAuthenticationService>(); 
     var userService = new Mock<IUserService>(); 
     var dictService = new Mock<IDictionaryService>(); 
     var shoppingBasketService = new Mock<IShoppingBasketService>(); 

     //Create the service provider mock and pass in the IRepositoryFactory so that it isn't instantiating real repositories 
     var repoFactory = new Mock<IRepositoryFactory>(); 
     var serviceProvider = new Mock<ServiceProvider>((IRepositoryFactory)repoFactory.Object); 

     var context = new Mock<HttpContextBase> { DefaultValue = DefaultValue.Mock }; 
     var sessionVars = new Mock<SessionVars>(); 

     [SetUp] 
     AccountController controller = new AccountController(serviceProvider.Object, sessionVars.Object) 
     { 
      FormsService = formsService.Object, 
      MembershipService = membershipService.Object, 
      UserService = userService.Object, 
      DictionaryService = dictService.Object, 
      ShoppingService = shoppingBasketService.Object 
     }; 
     controller.ControllerContext = new ControllerContext() 
     { 
      Controller = controller, 
      RequestContext = new RequestContext(context.Object, new RouteData()) 
     }; 
    } 

[TestFixture] 
public class when_getting_sign_in : MembershipContext 
{ 
    [Test] 
    public void Should_return_view() 
    { 
     // Act    
     ActionResult result = controller.SignIn(); 

     // Assert    
     Assert.IsInstanceOf<ViewResult>(result); 
    } 

    [Test] 
    public void Should_do_another_test() 
    { 
     ... another test etc 
    } 
} 
+0

C'est ce que je fais, faire des mocks membres de la classe de test de base et avoir une méthode d'installation commune pour ceux-ci. –

1

Une chose que vous pouvez faire est d'utiliser la méthode Mock.Get (http://api.moq.me/html/C6B12927.htm) pour récupérer le mock pour une instance d'objet donnée. Une autre option serait de refactoriser votre code et de stocker des références à vos objets simulés dans des variables d'instance de votre classe de test (si tous les tests de la classe de test le requièrent) ou une structure de données simple (si seulement certains tests les exigera). Essayez d'utiliser un contexte pour configurer tous vos mocks, puis utilisez test fixtures qui hérite de votre contexte.

+0

Oh wow, je ne savais pas à propos de celui-ci. Je suis sûr que ça va être utile pour quelque chose pour moi plus tard :) –