2010-07-15 8 views
5

Sto iniziando dal framework Moq e lo adoro assolutamente. Sto scrivendo alcuni test del controller che hanno diversi servizi e interfacce per organizzare il mio controller per il test. Mi piacerebbe modularizzarlo un po 'di più, e ho pensato che sarebbe stato un compito banale, ma si rivela essere un po' più complicato di quanto pensassi.Test del controller Moq con setup ripetuto

Ecco un semplice test di unità che devo mostrare un esempio:

[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); 
} 

Quello che mi piacerebbe essere in grado di fare è prendere tutto nel #region ed estrarre che fuori in un metodo di supporto o Metodo [Setup], ma se lo faccio, allora non ho accesso a ogni servizio di simulazione per impostare le aspettative.

C'è qualcosa che mi manca qui, o devo davvero copiare e incollare questo pezzo di codice Arrange in ogni test di Unità?

risposta

3

Prova a utilizzare un contesto per configurare tutti i tuoi mock, quindi usa test fixtures che eredita il tuo contesto. Metti i test dentro questi infissi e violà! Questo codice potrebbe non essere esattamente adatto al framework che stai utilizzando. Se è NUnit, lo sarà. Ma la teoria è 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

Questo è quello che faccio, rendere i mock membri della classe di test di base e avere un metodo di impostazione comune per quelli. –

1

Una cosa che si potrebbe fare è usare il metodo Mock.Get (http://api.moq.me/html/C6B12927.htm) per recuperare la simulazione di una determinata istanza di oggetto.
Un'altra opzione potrebbe essere il refactoring del codice e memorizzare i riferimenti ai propri oggetti mock nelle variabili di istanza della classe di test (se tutti i test nella classe di test li richiedono) o forse una semplice struttura di dati (se solo alcuni dei test li richiederà).

+0

Oh, wow, non sapevo di questo. Sono sicuro che sarà utile per qualcosa per me più avanti :) –