【问题标题】:New to AutoFixture trying to get my head around it and I can't see it helping meAutoFixture 的新手试图了解它,但我看不到它对我有帮助
【发布时间】:2013-05-09 06:11:02
【问题描述】:

目前,我正在使用定制的假对象,在幕后使用 NSubstitute 来创建实际对象,但随着项目的发展,它变得非常难以维护,所以我正在尝试寻找替代品,我希望AutoFixture 是适合这项工作的工具。

我阅读了文档,但我很苦恼,因为文档很少甚至没有,我阅读了 Mark Seemann 的大部分博客文章,包括 CheatSheet。

我很难掌握的一件事是如何使用具有参数的构造函数创建对象,在我的情况下,我需要将参数传递给 CsEmbeddedRazorViewEngine 以及将 HttpRequestBase 传递给 ControllerContext。

我看到它的方式是我需要创建一个假对象,最后创建一个将它们注入到的自定义对象

我还研究了 NBuilder,在那里传递参数似乎稍微简单一些,但我听说过关于 AutoFixture 的好消息,我想试一试。 :)

我正在尝试减少我拥有的假对象的数量,所以这是一个真正的测试,我怎样才能用 AutoFixture 做同样的事情?

[Theory, 
 InlineData("en-US"), 
 InlineData("en-us"), 
 InlineData("en")]
public void Should_return_the_default_path_of_the_view_for_enUS(string language)
{
    // Arrange
    const string EXPECTED_VIEW_PATH = "~/MyAssemblyName/Views/Home/Index.cshtml";

    CsEmbeddedRazorViewEngine engine = CsEmbeddedRazorViewEngineFactory.Create(ASSEMBLY_NAME, VIEW_PATH, string.Empty);

    string[] userLanguage = { language };

    HttpRequestBase request = FakeHttpRequestFactory.Create(userLanguage);

    ControllerContext controllerContext = FakeControllerContextFactory.Create(request);

    // Act
    ViewEngineResult result = engine.FindPartialView(controllerContext, VIEW_NAME, false);

    // Assert
    RazorView razorView = (RazorView)result.View;

    string actualViewPath = razorView.ViewPath;

    actualViewPath.Should().Be(EXPECTED_VIEW_PATH);
}

附:我使用 xUnit 作为我的测试框架和 NSubstitute 作为我的模拟框架我应该安装 AutoFixture.Xunit 和 AutoFixture.AutoNSubstitute 吗?

更新:在对它了解得越来越多之后,我想它不是适合这项工作的工具,因为我试图用 AutoFixture 代替我的测试替身工厂,而不是用它来设置我的 SUT。

由于奇怪的原因,我认为 NBuilder 正在做同样的事情,据我所知,它们是非常不同的工具。

所以经过一番思考,我想我会去改变我在我的测试替身工厂中使用的方法到对象,然后使用 AutoFixture 创建我的 SUT 并将我的测试替身注入到它。

【问题讨论】:

    标签: autofixture


    【解决方案1】:

    注意:我没有CsEmbeddedRazorViewEngine 类型和所有其他自定义类型的源代码。

    这是可以用 AutoFixture 编写的方法:

    [Theory]
    [InlineAutoWebData("en-US", "about", "~/MyAssemblyName/Views/Home/Index.cshtml")]
    [InlineAutoWebData("en-US", "other", "~/MyAssemblyName/Views/Home/Index.cshtml")]
    public void Should_return_the_default_path_of_the_view_for_enUS(
        string language, 
        string viewName,
        string expected,
        ControllerContext controllerContext,
        CsEmbeddedRazorViewEngine sut)
    {
        var result = sut.FindPartialView(controllerContext, viewName, false);
        var actual = ((RazorView)result.View).ViewPath;
    
        actual.Should().Be(expected);
    }
    

    工作原理

    它使用 AutoFixture 本身以及用于 xUnit.net 和 NSubstitute 的胶水库:

    PM> Install-Package AutoFixture.Xunit
    PM> Install-Package AutoFixture.AutoNSubstitute
    

    使用InlineAutoWebData,您实际上将内联值和 AutoFixture 自动生成的数据值结合在一起——还包括使用 NSubstitute 进行自动模拟。

    internal class InlineAutoWebDataAttribute : CompositeDataAttribute
    {
        internal InlineAutoWebDataAttribute(params object[] values)
            : base(
                new InlineDataAttribute(values),
                new CompositeDataAttribute(
                    new AutoDataAttribute(
                        new Fixture().Customize(
                            new WebModelCustomization()))))
        {
        }
    }
    

    备注

    您实际上可以用AutoNSubstituteCustomization 替换上面的WebModelCustomization 自定义,它可以工作。

    但是,假设您使用的是 ASP.NET MVC 4,您需要自定义 Fixture 实例:

    internal class WebModelCustomization : CompositeCustomization
    {
        internal WebModelCustomization()
            : base(
                new MvcCustomization(),
                new AutoNSubstituteCustomization())
        {
        }
    
        private class MvcCustomization : ICustomization
        {
            public void Customize(IFixture fixture)
            {
                fixture.Customize<ControllerContext>(c => c
                    .Without(x => x.DisplayMode));
    
                // Customize the CsEmbeddedRazorViewEngine type here.
            }
        }
    }
    

    进一步阅读

    【讨论】:

    • 不客气!请注意,我不希望测试通过,因为您必须使用自定义类型完成MvcCustomization。另外请注意,单元测试 ASP.NET MVC 4 很难..
    • 是的,我只是尝试运行它,哈哈……在我开始使用它之前,我必须阅读更多关于它的信息,因为关于这个特定的库似乎有很多东西要学习。
    【解决方案2】:

    我最终这样做了。

    [Theory,
     InlineData("en-US", "Index", "~/MyAssemblyName/Views/Home/Index.cshtml"),
     InlineData("en-us", "Index", "~/MyAssemblyName/Views/Home/Index.cshtml"),
     InlineData("en", "Index", "~/MyAssemblyName/Views/Home/Index.cshtml")]
    public void Should_return_the_default_path_of_the_view(string language, string viewName, string expected)
    {
        // Arrange
        CsEmbeddedRazorViewEngine engine = new CsEmbeddedRazorViewEngineFixture();
    
        ControllerContext controllerContext = FakeControllerContextBuilder.WithLanguage(language).Build();
    
        // Act
        ViewEngineResult result = engine.FindPartialView(controllerContext, viewName, false);
    
        // Assert
        string actualViewPath = ((RazorView)result.View).ViewPath;
    
        actualViewPath.Should().Be(expected);
    }
    

    我封装了细节以将我的 SUT 设置到一个夹具中,并使用构建器模式来处理我的假货,我认为它现在可读且非常简单。

    虽然 AutoFixture 看起来很酷,但学习曲线似乎很长,我需要投入足够的时间来理解它,现在,我想清理我的单元测试并使其更具可读性。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-15
      • 1970-01-01
      • 1970-01-01
      • 2014-06-18
      相关资源
      最近更新 更多