通过重复设置进行最小起订量控制器测试

发布于 2024-09-09 17:12:03 字数 1900 浏览 2 评论 0原文

我正在开始使用 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] 中方法,但如果我这样做,那么我将无法访问每个模拟服务来设置期望。

我在这里遗漏了什么,还是我真的必须在每个单元测试中复制并粘贴这段排列代码?

I am getting started on the Moq framework and absolutely love it. I am writing some controller tests that have several services and interfaces to Arrange my controller for the test. I'd love to modularize it a bit more, and thought this would be a trivial task, but it turns out to be a bit trickier than I thought.

Here is one simple unit test that I have to show an example:

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

What I'd like to be able to do is take everything in the #region and extract that out into a helper method or [Setup] method, but if I do that, then I don't have access to each mock service to setup expectations.

Is there something I'm missing here, or do I really have to copy-and-paste this chunk of Arrange code in each Unit test?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你在我安 2024-09-16 17:12:03

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

Try using a context to setup all your mocks, then use test fixtures that inherit your context. Put the tests inside these fixtures and violà! This code might not be exactly right for the framework you are using. If it is NUnit then it will be. But the theory is there.

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
    }
}
盛夏已如深秋| 2024-09-16 17:12:03

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

One thing you could do is use the Mock.Get method (http://api.moq.me/html/C6B12927.htm) to retrieve the mock for a given object instance.
Another option would be to refactor your code and store references to your mock objects in instance variables of your test class (if all of the tests in the test class require them) or perhaps a simple data structure (if only some of the tests will require them).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文