gpt4 book ai didi

asp.net - 如何在 ASP.NET MVC3 中对 ValueProviderFactories 进行单元测试?

转载 作者:行者123 更新时间:2023-12-04 04:08:06 24 4
gpt4 key购买 nike

我们想将我们的项目从 ASP.NET MVC 2 升级到 3。我们的大多数测试都成功了,但也有一些在 ValueProviderFactories.Factories.GetValueProvider(context) 上失败了.

这是一个说明问题的简单测试类。

[TestFixture]
public class FailingTest
{
[Test]
public void Test()
{
var type = typeof(string);
// any controller
AuthenticationController c = new AuthenticationController();
var httpContext = new Mock<HttpContextBase>();
var context = c.ControllerContext = new ControllerContext(httpContext.Object, new RouteData(), c);

IModelBinder converter = ModelBinders.Binders.GetBinder(type);
var bc = new ModelBindingContext
{
ModelName = "testparam",
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, type),
ValueProvider = ValueProviderFactories.Factories.GetValueProvider(context)
};
Console.WriteLine(converter.BindModel(context, bc));
}
}

异常“对象引用未设置为对象的实例。”在 ValueProviderFactories.Factories.GetValueProvider(context) 时抛出叫做。堆栈跟踪如下所示:
Microsoft.Web.Infrastructure.dll!Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.CollectionReplacer.GetUnvalidatedCollections(System.Web.HttpContext context) + 0x23 bytes   
Microsoft.Web.Infrastructure.dll!Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.GetUnvalidatedCollections(System.Web.HttpContext context, out System.Collections.Specialized.NameValueCollection form, out System.Collections.Specialized.NameValueCollection queryString, out System.Collections.Specialized.NameValueCollection headers, out System.Web.HttpCookieCollection cookies) + 0xbe bytes
System.Web.WebPages.dll!System.Web.Helpers.Validation.Unvalidated(System.Web.HttpRequest request) + 0x73 bytes
System.Web.WebPages.dll!System.Web.Helpers.Validation.Unvalidated(System.Web.HttpRequestBase request) + 0x25 bytes
System.Web.Mvc.DLL!System.Web.Mvc.FormValueProviderFactory..ctor.AnonymousMethod__0(System.Web.Mvc.ControllerContext cc) + 0x5a bytes
System.Web.Mvc.DLL!System.Web.Mvc.FormValueProviderFactory.GetValueProvider(System.Web.Mvc.ControllerContext controllerContext) + 0xa0 bytes
System.Web.Mvc.DLL!System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider.AnonymousMethod__7(System.Web.Mvc.ValueProviderFactory factory) + 0x4a bytes
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Web.Mvc.ValueProviderFactory,<>f__AnonymousType2<System.Web.Mvc.ValueProviderFactory,System.Web.Mvc.IValueProvider>>.MoveNext() + 0x24d bytes
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<<>f__AnonymousType2<System.Web.Mvc.ValueProviderFactory,System.Web.Mvc.IValueProvider>,System.Web.Mvc.IValueProvider>.MoveNext() + 0x2ba bytes
mscorlib.dll!System.Collections.Generic.List<System.Web.Mvc.IValueProvider>.List(System.Collections.Generic.IEnumerable<System.Web.Mvc.IValueProvider> collection) + 0x1d8 bytes
System.Core.dll!System.Linq.Enumerable.ToList<System.Web.Mvc.IValueProvider>(System.Collections.Generic.IEnumerable<System.Web.Mvc.IValueProvider> source) + 0xb5 bytes
System.Web.Mvc.DLL!System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(System.Web.Mvc.ControllerContext controllerContext) + 0x24d bytes
test.DLL!FailingTest.Test() Line 31 + 0xf9 bytes C#

我想知道它抛出异常的原因并看到:
public static ValidationUtility.UnvalidatedCollections GetUnvalidatedCollections(HttpContext context)
{
return (ValidationUtility.UnvalidatedCollections) context.Items[_unvalidatedCollectionsKey];
}

那么,当我们依赖 HttpContext.Current 时,我们是否回到了过去? ?如何解决它?

最佳答案

这可以通过代理访问 HttpContext 到忽略它的 ValueProvider 来轻松解决。

我已经在我的博文中解释了一切:Unit test actions with ValueProviderFactories in ASP.NET MVC3 .

关键是这段代码:

public static class ValueProviderFactoresExtensions {
public static ValueProviderFactoryCollection ReplaceWith<TOriginal>(this ValueProviderFactoryCollection factories, Func<ControllerContext, NameValueCollection> sourceAccessor) {
var original = factories.FirstOrDefault(x => typeof(TOriginal) == x.GetType());
if (original != null) {
var index = factories.IndexOf(original);
factories[index] = new TestValueProviderFactory(sourceAccessor);
}
return factories;
}

class TestValueProviderFactory : ValueProviderFactory {
private readonly Func<ControllerContext, NameValueCollection> sourceAccessor;


public TestValueProviderFactory(Func<ControllerContext, NameValueCollection> sourceAccessor) {
this.sourceAccessor = sourceAccessor;
}


public override IValueProvider GetValueProvider(ControllerContext controllerContext) {
return new NameValueCollectionValueProvider(sourceAccessor(controllerContext), CultureInfo.CurrentCulture);
}
}
}

所以它可以用作:
ValueProviderFactories.Factories
.ReplaceWith<FormValueProviderFactory>(ctx => ctx.HttpContext.Request.Form)
.ReplaceWith<QueryStringValueProviderFactory>(ctx => ctx.HttpContext.Request.QueryString);

这实际上很容易:)

更新 :如评论中所述,您应该记住:
  • 设置 ctx.HttpContext.Request.ContentType属性为某个非空值,否则 JsonValueProviderFactory 将抛出异常。我更喜欢在那里创建一个模拟并设置默认值。
  • 替换HttpFileCollectionValueProviderFactory因为它可以在绑定(bind)期间使用。
  • 注意项目中可能存在的其他依赖项。
  • 关于asp.net - 如何在 ASP.NET MVC3 中对 ValueProviderFactories 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4603741/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com