测试MVC控制器动作HttpAcceptAttribute动词

时间:2009-10-18 01:47:04

标签: c# unit-testing model-view-controller xunit.net acceptverbs

对控制器动作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));
}

由于 MAC

4 个答案:

答案 0 :(得分:3)

没有反射和魔术字符串,在不破坏单元测试的情况下轻松重命名控制器和方法:

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

答案 1 :(得分: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;
        }

    }

}

使用

public void FilterControllerTestRemoveFilterByProductAttributeIsOfTypePost()
{
    FilterController controller = new FilterController();
    MvcAssert.HasPostAction(controller, "RemoveFilterByProduct", 1);
}

答案 2 :(得分:1)

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

    }

}

答案 3 :(得分:0)

有点修改版Darin的解决方案。

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