URL Unittesting. Действие (использующий насмешки носорога?)

function sucess() {
 message = ["Good!","Awesome!","Super!","Nice!","Great!"];
 return message[Math.floor(Math.random() * message.length)];
}

 $(document).ready(function(){
     var validator = $(".contactform").validate({ ...
              success: function(label) {
    label.addClass("valid").text(success());
 }
      }); //end form validate code
         });
12
задан Kristoffer Ahl 5 June 2009 в 06:58
поделиться

3 ответа

Причина, по которой он не работает, заключается в том, что внутри объекта RouteCollection вызывается метод ApplyAppPathModifier на HttpResponseBase. Похоже, что фиктивный код Хансельмана не устанавливает никаких ожиданий для этого метода, поэтому он возвращает значение null, поэтому все ваши вызовы метода Action в UrlHelper возвращают пустую строку. Исправление состояло бы в том, чтобы настроить ожидание в методе ApplyAppPathModifier макета HttpResponseBase, чтобы просто вернуть значение, которое ему передано. Я не эксперт по Rhino Mocks, поэтому не совсем уверен в синтаксисе. Если вы используете Moq, это будет выглядеть так:

httpResponse.Setup(r => r.ApplyAppPathModifier(It.IsAny<string>()))
    .Returns((string s) => s);

Или, если вы просто используете скрученный вручную макет, сработает что-то вроде этого:

internal class FakeHttpContext : HttpContextBase
{
    private HttpRequestBase _request;
    private HttpResponseBase _response;

    public FakeHttpContext()
    {
        _request = new FakeHttpRequest();
        _response = new FakeHttpResponse();
    }

    public override HttpRequestBase Request
    {
        get { return _request; }
    }

    public override HttpResponseBase Response
    {
        get { return _response; }
    }
}

internal class FakeHttpResponse : HttpResponseBase
{
    public override string ApplyAppPathModifier(string virtualPath)
    {
        return virtualPath;
    }
}

internal class FakeHttpRequest : HttpRequestBase
{
    private NameValueCollection _serverVariables = new NameValueCollection();

    public override string ApplicationPath
    {
        get { return "/"; }
    }

    public override NameValueCollection ServerVariables
    {
        get { return _serverVariables; }
    }
}

Приведенный выше код должен быть минимально необходимой реализацией HttpContextBase, чтобы чтобы пройти модульное тестирование для UrlHelper. Я попробовал, и это сработало. Надеюсь это поможет.

11
ответ дан 2 December 2019 в 21:04
поделиться

Я знаю, что это не дает прямого ответа на ваш вопрос, но есть ли причина, по которой вы пытаетесь написать свой собственный общий метод расширения, а не использовать тот, который доступен в MVC Futures сборка? (Microsoft.Web.Mvc.dll) Или вы на самом деле пытаетесь выполнить модульное тестирование метода расширения msft?

[Изменить 1] Извините, я думал о вспомогательном расширении Html в Futures.

А пока я попробую свои силы в модульном тесте, чтобы узнать, получу ли я тот же результат.

[Изменить 2] Хорошо, так что это еще не полностью работает, но это не взрывается. Результат просто возвращает пустую строку. Я взял несколько насмешливых помощников Mvc от Скотта Хансельмана по по этой ссылке.

Я также создал метод Url.Action вместе с вспомогательными методами, которые я скопировал из источника Mvc:

public static string Action<TController>(this UrlHelper helper, Expression<Action<TController>> action) where TController : Controller
{
    string result = BuildUrlFromExpression<TController>(helper.RequestContext, helper.RouteCollection, action);
    return result;
}

public static string BuildUrlFromExpression<TController>(RequestContext context, RouteCollection routeCollection, Expression<Action<TController>> action) where TController : Controller
{
    RouteValueDictionary routeValuesFromExpression = GetRouteValuesFromExpression<TController>(action);
    VirtualPathData virtualPath = routeCollection.GetVirtualPath(context, routeValuesFromExpression);
    if (virtualPath != null)
    {
        return virtualPath.VirtualPath;
    }
    return null;
}

public static RouteValueDictionary GetRouteValuesFromExpression<TController>(Expression<Action<TController>> action) where TController : Controller
{
    if (action == null)
    {
        throw new ArgumentNullException("action");
    }
    MethodCallExpression body = action.Body as MethodCallExpression;
    if (body == null)
    {
        throw new ArgumentException("MvcResources.ExpressionHelper_MustBeMethodCall", "action");
    }
    string name = typeof(TController).Name;
    if (!name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase))
    {
        throw new ArgumentException("MvcResources.ExpressionHelper_TargetMustEndInController", "action");
    }
    name = name.Substring(0, name.Length - "Controller".Length);
    if (name.Length == 0)
    {
        throw new ArgumentException("MvcResources.ExpressionHelper_CannotRouteToController", "action");
    }
    RouteValueDictionary rvd = new RouteValueDictionary();
    rvd.Add("Controller", name);
    rvd.Add("Action", body.Method.Name);
    AddParameterValuesFromExpressionToDictionary(rvd, body);
    return rvd;
}

private static void AddParameterValuesFromExpressionToDictionary(RouteValueDictionary rvd, MethodCallExpression call)
{
    ParameterInfo[] parameters = call.Method.GetParameters();
    if (parameters.Length > 0)
    {
        for (int i = 0; i < parameters.Length; i++)
        {
            Expression expression = call.Arguments[i];
            object obj2 = null;
            ConstantExpression expression2 = expression as ConstantExpression;
            if (expression2 != null)
            {
                obj2 = expression2.Value;
            }
            else
            {
                Expression<Func<object>> expression3 = Expression.Lambda<Func<object>>(Expression.Convert(expression, typeof(object)), new ParameterExpression[0]);
                obj2 = expression3.Compile()();
            }
            rvd.Add(parameters[i].Name, obj2);
        }
    }
}

] И, наконец, вот тест, который я провожу:

    [Test]
    public void GenericActionLinkHelperTest()
    {
        RouteRegistrar.RegisterRoutesTo(RouteTable.Routes);

        var mocks = new MockRepository();
        var context = mocks.FakeHttpContext(); // the extension from hanselman

        var helper = new UrlHelper(new RequestContext(context, new RouteData()), RouteTable.Routes);
        string result = helper.Action<ProjectsController>(x => x.Index());

        // currently outputs an empty string, so something is fudded up.
        Console.WriteLine(result);
    }

Пока не знаю, почему результат - пустая строка, но я буду продолжать возиться с этим, поскольку у меня есть время. Мне было бы любопытно узнать, найдете ли вы пока решение.

1
ответ дан 2 December 2019 в 21:04
поделиться

Я смог протестировать метод BuildUrlFromExpression, но мне нужно было зарегистрировать RouteTable.Routes перед запуском тестов:

[ClassInitialize]
public static void FixtureSetUp(TestContext @__testContext)
{
    MvcApplication.RegisterRoutes(RouteTable.Routes);
}

Затем выделите/настройте эти свойства:

HttpRequestBase request = mocks.PartialMock<HttpRequestBase>();
request.Stub(r => r.ApplicationPath).Return(string.Empty);

HttpResponseBase response = mocks.PartialMock<HttpResponseBase>();
SetupResult.For(response.ApplyAppPathModifier(Arg<String>.Is.Anything)).IgnoreArguments().Do((Func<string, string>)((arg) => { return arg; }));

После этого метод BuildUrlFromExpression вернул uls, как и ожидалось.

2
ответ дан 2 December 2019 в 21:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: