Тесты контроллера Moq с повторной настройкой - PullRequest
5 голосов
/ 15 июля 2010

Я начинаю работать с Moq и очень люблю его. Я пишу несколько тестов контроллера, которые имеют несколько сервисов и интерфейсов, чтобы организовать мой контроллер для теста. Мне бы хотелось немного его модульнить, и я подумал, что это будет тривиальной задачей, но оказалось, что это немного сложнее, чем я думал.

Вот один простой модульный тест, который я должен показать на примере:

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

То, что я хотел бы сделать, это взять все в #region и извлечь это во вспомогательный метод или метод [Setup], но если я это сделаю, то у меня нет доступа к каждому макет службы для установки ожиданий.

Есть ли что-то, чего мне здесь не хватает, или мне действительно нужно копировать и вставлять этот фрагмент кода Arrange в каждом модульном тесте?

Ответы [ 2 ]

3 голосов
/ 16 июля 2010

Попробуйте использовать контекст, чтобы настроить все свои макеты, затем используйте тестовые приборы , которые наследуют ваш контекст. Положите тесты внутри этих приспособлений и виол! Этот код может быть не совсем подходящим для используемой вами платформы. Если это NUnit, то это будет. Но теория есть.

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
    }
}
1 голос
/ 15 июля 2010

Одна вещь, которую вы могли бы сделать, это использовать метод Mock.Get (http://api.moq.me/html/C6B12927.htm), чтобы получить макет для данного экземпляра объекта.
Другой вариант - рефакторинг вашего кода и сохранение ссылок на ваши фиктивные объекты.в переменных экземпляра вашего тестового класса (если все тесты в тестовом классе требуют их) или, возможно, в простой структуре данных (если только некоторые тесты будут требовать их).

...