通过一次测试对所有控制器进行单元测试

发布于 2024-09-24 17:07:11 字数 317 浏览 5 评论 0原文

我刚刚创建了一个操作过滤器,我想将其应用于几乎所有控制器(包括稍后引入的任何新控制器)。

我认为真正有用的单元测试是循环遍历每个控制器并验证是否满足某些条件,然后操作过滤器将影响结果。

创建一个针对多个控制器的单元测试是否明智?任何人都可以分享已证明有用的类似测试的代码吗?

编辑:刚刚意识到 测试操作过滤器可能有问题。不过,如果您有关于控制器大规模测试的想法可以分享……

I just created an action filter that I want to apply to nearly all of my controllers (including any new ones that are introduced later on).

I figure a really useful unit test would be one that cycles through each controller and verifies that if certain criteria are met, then the action filter will impact the result.

Is it wise to create a unit test that hits multiple controllers? Can anyone share code from a similar test that has proven useful?

EDIT: Just realized that testing an action filter might be problematic. Still, if you have thoughts to share on mass testing of controllers...

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

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

发布评论

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

评论(3

情绪 2024-10-01 17:07:11

不建议在测试中一次测试多于一件事。

您还应该避免测试中的逻辑(switch、if、else、foreach、for、while),因为测试的可读性较差,并且可能会引入隐藏的错误。

许多简单的、可读的、因此可维护的测试,每个只测试一件事,比一个非常复杂的测试要好得多。

对您的编辑的响应

可以通过将过滤器与属性分离来实现测试过滤器。下面是一个示例:LoadMembershipTypeListFilter 类具有使用测试假货所需的“接缝”。这是过滤器中要测试的逻辑的地方。

public class LoadMembershipTypeListFilter : IActionFilter
{
    private IMembershipTypeProvider _provider;
    private IMembershipTypeAdminMapper _mapper;

    public LoadMembershipTypeListFilter(IMembershipTypeProvider provider, IMembershipTypeAdminMapper mapper)
    {
        _provider = provider;
        _mapper = mapper;
    }

    #region IActionFilter Members
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //implementation...
    }
    #endregion
}

这里的属性使用过滤器,此示例通过调用服务定位器来解析过滤器所需的依赖关系:

public class LoadMembershipTypeListAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var filter = new LoadMembershipTypeListFilter(IocResolve.Resolve<IMembershipTypeProvider>(), IocResolve.Resolve<IMembershipTypeAdminMapper>());
        filter.OnActionExecuting(filterContext);
    }
}

并且您的控制器使用该属性:

[LoadMembershipTypeList]
public ActionResult Create()
{
    return View();
}

It is not recommended to test more than one thing at a time in tests.

You should also avoid logic in tests (switch, if, else, foreach, for, while) as the test is less readable and possibly introduces hidden bugs.

Many simple, readable, and therefore maintainable tests that are only testing one thing each are far preferable to one test with a lot of complexity.

RESPONSE TO YOUR EDIT

Testing filters can be achieved by separating the filter from the attribute. Here is an example: The LoadMembershipTypeListFilter class has the 'seams' needed to use test fakes. This is where your logic in your filter is that is to be tested.

public class LoadMembershipTypeListFilter : IActionFilter
{
    private IMembershipTypeProvider _provider;
    private IMembershipTypeAdminMapper _mapper;

    public LoadMembershipTypeListFilter(IMembershipTypeProvider provider, IMembershipTypeAdminMapper mapper)
    {
        _provider = provider;
        _mapper = mapper;
    }

    #region IActionFilter Members
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //implementation...
    }
    #endregion
}

And the attribute here uses the filter, this example resolves the dependencies the filter requires by a call to the service locator:

public class LoadMembershipTypeListAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var filter = new LoadMembershipTypeListFilter(IocResolve.Resolve<IMembershipTypeProvider>(), IocResolve.Resolve<IMembershipTypeAdminMapper>());
        filter.OnActionExecuting(filterContext);
    }
}

And your controller uses the attribute:

[LoadMembershipTypeList]
public ActionResult Create()
{
    return View();
}
千里故人稀 2024-10-01 17:07:11

由于您很可能无论如何都会为每个控制器编写单元测试,因此您始终可以拥有一个测试操作过滤器的单元测试基类。任何使用操作过滤器的控制器测试都将从此类继承来测试操作过滤器。

Since you are most likely going to write unit tests for each controller anyway, you could always just have a unit test base class that tests the action filter. Any controller test that uses the action filter would inherit from this class to also test the action filter.

得不到的就毁灭 2024-10-01 17:07:11

我想说那时你正在测试基础设施。如果您想检查过滤器是否应用在您期望的方法中,请使用反射 + 匹配您期望匹配的方法列表。

也许您确实想检查这些方法是否具有特定的签名,上面的方法也适用于此。

如果您想测试操作过滤器,请直接对其进行操作。也许您真正需要的是确保不同的结果/模型适用于过滤器。

I'd say at that point you are testing the infrastructure. If you want to check the filters are applied in the methods you expect, then use reflection + match a list of methods you expect to be matched.

Maybe you do want to check that the methods have a certain signature, the above would work for that as well.

If you want to test the action filter, go directly against it. Maybe what you really need is making sure different results/models work with the filter.

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