7

为了干掉我的单元测试,我尝试使用 AutoFixture 作为 IoC 容器来实例化我的被测系统 (SUT),在这种特殊情况下是 ASP.NET MVC Controller。因此,我想自定义 AutoFixture 以创建没有自动属性的控制器。

我尝试为 . 添加自定义ControllerBase,但它似乎不适用于ControllerBase.

fixture.Customize<ControllerBase>(c => c.OmitAutoProperties());

这是我希望能够编写的测试示例:

    [Theory, AutoFixtureData]
    public void ControllerTest(AccountController controller) {
        Assert.Equal(default(UrlHelper), controller.Url);
    }

当然,如果我为项目中的每个特定控制器手动添加一个自定义项,它就会起作用,但谁愿意这样做呢?有没有更好的办法?

4

1 回答 1

8

以下自定义通过了上述测试,并按照您的要求进行

public class MvcCostumization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Customizations.Add(
            new FilteringSpecimenBuilder(
                new MethodInvoker(new ModestConstructorQuery()),
                new ControllerSpecification()));
    }

    private class ControllerSpecification : IRequestSpecification
    {
        public bool IsSatisfiedBy(object request)
        {
            var t = request as Type;
            if (t == null)
                return false;

            return typeof(ControllerBase).IsAssignableFrom(t);
        }
    }
}

但是,这会禁用所有 MVC 控制器的所有属性,包括UserHttpContextModelStateRequestResponse等。您可能在单元测试中需要这些属性,所以您确定要这样做吗?

我将是第一个同意 MVCController基类是一个巨大的 SRP 违规的人,但它是一个给我们的类,所以我们无能为力,只能尽力利用它。

通常,您只需要稍微扭转一下 AutoFixture 即可自动填充大部分属性。

在 MVC 3 项目中,这与AutoMoq 扩展相结合,足以创建控制器实例:

fixture.Customize<ModelBindingContext>(c => c
    .Without(x => x.Model)
    .Without(x => x.ModelType));
fixture.Inject(CultureInfo.CurrentCulture);
于 2012-12-14T08:50:18.447 回答