【问题标题】:Moq controller tests with repeated setupMoq 控制器测试重复设置
【发布时间】:2010-07-15 18:44:11
【问题描述】:

我开始使用 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 代码?

【问题讨论】:

    标签: c# unit-testing asp.net-mvc-2 nunit moq


    【解决方案1】:

    尝试使用上下文来设置您的所有模拟,然后使用继承您的上下文的test fixtures。将测试放在这些固定装置中,然后中提琴!此代码可能不完全适合您使用的框架。如果它是 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
        }
    }
    

    【讨论】:

    • 这就是我所做的,制作基本测试类的模拟成员,并为这些成员提供一个通用的设置方法。
    【解决方案2】:

    您可以做的一件事是使用 Mock.Get 方法 (http://api.moq.me/html/C6B12927.htm) 检索给定对象实例的模拟。
    另一种选择是重构代码并将对模拟对象的引用存储在测试类的实例变量中(如果测试类中的所有测试都需要它们)或者可能是一个简单的数据结构(如果只有一些测试需要他们)。

    【讨论】:

    • 哦,哇,我不知道这个。我相信它稍后会对我有用:)
    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    相关资源
    最近更新 更多