测试 MVC 控制器操作 HttpAcceptAttribute 动词

发布于 2024-08-07 21:46:06 字数 740 浏览 13 评论 0原文

对控制器操作 HttpAcceptAttribute 动词进行单元测试的最佳方法是什么?

到目前为止,我有以下内容,但它太丑了,连母亲都不喜欢它,而且不太灵活。有更好的办法吗?

[Fact] // using xUnit, mocking controller in class
public void FilterControllerTestRemoveFilterByProductAttributeIsOfTypePost()
{
    Type[] paramTypes = new[] { typeof(int) };
    var method = typeof(FilterController).GetMethod("MyMethod", paramTypes);

    var attributes = method.GetCustomAttributes(typeof(AcceptVerbsAttribute), false).Cast<AcceptVerbsAttribute>().SingleOrDefault();
    Assert.NotNull(attributes);
    Assert.Equal(1, attributes.Verbs.Count());
    Assert.True(attributes.Verbs.First().Equals(HttpVerbs.Post.ToString(), StringComparison.InvariantCultureIgnoreCase));
}

谢谢 苹果

What is the best way to unit test the controller action HttpAcceptAttribute verbs?

So far I have the following but it's so ugly even a mother couldn't love it and not very flexible. Is there a better way?

[Fact] // using xUnit, mocking controller in class
public void FilterControllerTestRemoveFilterByProductAttributeIsOfTypePost()
{
    Type[] paramTypes = new[] { typeof(int) };
    var method = typeof(FilterController).GetMethod("MyMethod", paramTypes);

    var attributes = method.GetCustomAttributes(typeof(AcceptVerbsAttribute), false).Cast<AcceptVerbsAttribute>().SingleOrDefault();
    Assert.NotNull(attributes);
    Assert.Equal(1, attributes.Verbs.Count());
    Assert.True(attributes.Verbs.First().Equals(HttpVerbs.Post.ToString(), StringComparison.InvariantCultureIgnoreCase));
}

Thanks
Mac

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

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

发布评论

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

评论(4

尴尬癌患者 2024-08-14 21:46:06

没有反射和魔术字符串,可以轻松重命名控制器和方法而不破坏单元测试:

[TestMethod]
public void HomeController_Index_Action_Should_Accept_Post_Verb_Only()
{
    Expression<Action<HomeController>> expression = (HomeController c) => c.Index(null);
    var methodCall = expression.Body as MethodCallExpression;
    var acceptVerbs = (AcceptVerbsAttribute[])methodCall.Method.GetCustomAttributes(typeof(AcceptVerbsAttribute), false);
    acceptVerbs.ShouldNotBeNull("");
    acceptVerbs.Length.ShouldBe(1);
    acceptVerbs[0].Verbs.First().ShouldBe("POST");
}

No reflection and magic strings, easy to rename controller and method without breaking the unit test:

[TestMethod]
public void HomeController_Index_Action_Should_Accept_Post_Verb_Only()
{
    Expression<Action<HomeController>> expression = (HomeController c) => c.Index(null);
    var methodCall = expression.Body as MethodCallExpression;
    var acceptVerbs = (AcceptVerbsAttribute[])methodCall.Method.GetCustomAttributes(typeof(AcceptVerbsAttribute), false);
    acceptVerbs.ShouldNotBeNull("");
    acceptVerbs.Length.ShouldBe(1);
    acceptVerbs[0].Verbs.First().ShouldBe("POST");
}
口干舌燥 2024-08-14 21:46:06
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Unknown.Tests
{

    public static class MvcAssert
    {

        public static MemberInfo[] HasPostAction(Controller controller, string actionName, int expectedCount)
        {
            if (controller == null)
                throw new ArgumentNullException("controller");

            if (string.IsNullOrEmpty(actionName))
                throw new ArgumentNullException("actionName");

            MemberInfo[] members = controller.GetType().FindMembers(
                MemberTypes.Method,
                BindingFlags.Public | BindingFlags.Instance,
                (m, c) => (m.Name == actionName && m.IsDefined(typeof(AcceptVerbsAttribute), false) && ((AcceptVerbsAttribute)Attribute.GetCustomAttribute(m, typeof(AcceptVerbsAttribute))).Verbs.Any((v) => v.Equals("Post", StringComparison.InvariantCultureIgnoreCase))),
                null);

            Assert.AreEqual<int>(expectedCount, members.Length);

            return members;
        }

    }

}

使用

public void FilterControllerTestRemoveFilterByProductAttributeIsOfTypePost()
{
    FilterController controller = new FilterController();
    MvcAssert.HasPostAction(controller, "RemoveFilterByProduct", 1);
}
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Unknown.Tests
{

    public static class MvcAssert
    {

        public static MemberInfo[] HasPostAction(Controller controller, string actionName, int expectedCount)
        {
            if (controller == null)
                throw new ArgumentNullException("controller");

            if (string.IsNullOrEmpty(actionName))
                throw new ArgumentNullException("actionName");

            MemberInfo[] members = controller.GetType().FindMembers(
                MemberTypes.Method,
                BindingFlags.Public | BindingFlags.Instance,
                (m, c) => (m.Name == actionName && m.IsDefined(typeof(AcceptVerbsAttribute), false) && ((AcceptVerbsAttribute)Attribute.GetCustomAttribute(m, typeof(AcceptVerbsAttribute))).Verbs.Any((v) => v.Equals("Post", StringComparison.InvariantCultureIgnoreCase))),
                null);

            Assert.AreEqual<int>(expectedCount, members.Length);

            return members;
        }

    }

}

Using

public void FilterControllerTestRemoveFilterByProductAttributeIsOfTypePost()
{
    FilterController controller = new FilterController();
    MvcAssert.HasPostAction(controller, "RemoveFilterByProduct", 1);
}
面犯桃花 2024-08-14 21:46:06
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MvcApplication4.Tests
{

    public static class MvcAssert
    {

        public static MethodInfo ActionExists(Controller controller, string actionName, HttpVerbs expectedVerbs, params Type[] paramTypes)
        {
            if (controller == null)
                throw new ArgumentNullException("controller");

            if (string.IsNullOrEmpty(actionName))
                throw new ArgumentNullException("actionName");

            int actualVerbs = 0;

            MethodInfo action = controller.GetType().GetMethod(actionName, paramTypes);
            Assert.IsNotNull(action, string.Format("The specified action '{0}' could not be found.", actionName));

            AcceptVerbsAttribute acceptVerb = Attribute.GetCustomAttribute(action, typeof(AcceptVerbsAttribute)) as AcceptVerbsAttribute;

            if (acceptVerb == null)
                actualVerbs = (int)HttpVerbs.Get;
            else
                actualVerbs = (int)Enum.Parse(typeof(HttpVerbs), string.Join(", ", acceptVerb.Verbs.ToArray()), true);

            Assert.AreEqual<int>(actualVerbs, (int)expectedVerbs);

            return action;
        }

    }

}
using System;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MvcApplication4.Tests
{

    public static class MvcAssert
    {

        public static MethodInfo ActionExists(Controller controller, string actionName, HttpVerbs expectedVerbs, params Type[] paramTypes)
        {
            if (controller == null)
                throw new ArgumentNullException("controller");

            if (string.IsNullOrEmpty(actionName))
                throw new ArgumentNullException("actionName");

            int actualVerbs = 0;

            MethodInfo action = controller.GetType().GetMethod(actionName, paramTypes);
            Assert.IsNotNull(action, string.Format("The specified action '{0}' could not be found.", actionName));

            AcceptVerbsAttribute acceptVerb = Attribute.GetCustomAttribute(action, typeof(AcceptVerbsAttribute)) as AcceptVerbsAttribute;

            if (acceptVerb == null)
                actualVerbs = (int)HttpVerbs.Get;
            else
                actualVerbs = (int)Enum.Parse(typeof(HttpVerbs), string.Join(", ", acceptVerb.Verbs.ToArray()), true);

            Assert.AreEqual<int>(actualVerbs, (int)expectedVerbs);

            return action;
        }

    }

}
栀梦 2024-08-14 21:46:06

达林解决方案的一点修改版本。

  [Fact]
  public void Delete_Verb(){
    VerifyVerb<HttpDeleteAttribute>(x=>x.Delete(null));
  }

  protected void VerifyVerb<TVerbType>(Expression<Action<T>> exp){
      var methodCall = exp.Body as MethodCallExpression;
      var acceptVerbs = methodCall.Method
        .GetCustomAttributes(typeof(TVerbType), false);
      acceptVerbs.Should().Not.Be.Null();
      acceptVerbs.Length.Should().Be(1);
  }

A bit modified version Darin`s solution.

  [Fact]
  public void Delete_Verb(){
    VerifyVerb<HttpDeleteAttribute>(x=>x.Delete(null));
  }

  protected void VerifyVerb<TVerbType>(Expression<Action<T>> exp){
      var methodCall = exp.Body as MethodCallExpression;
      var acceptVerbs = methodCall.Method
        .GetCustomAttributes(typeof(TVerbType), false);
      acceptVerbs.Should().Not.Be.Null();
      acceptVerbs.Length.Should().Be(1);
  }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文