Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

530 lines
20 KiB
C#

// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
using Microsoft.Web.UnitTestUtil;
using Moq;
using Xunit;
using Assert = Microsoft.TestCommon.AssertEx;
namespace Microsoft.Web.Mvc.ModelBinding.Test
{
public class ModelBinderProviderCollectionTest
{
[Fact]
public void ListWrappingConstructor()
{
// Arrange
ModelBinderProvider[] providers = new[]
{
new Mock<ModelBinderProvider>().Object,
new Mock<ModelBinderProvider>().Object
};
// Act
ModelBinderProviderCollection collection = new ModelBinderProviderCollection(providers);
// Assert
Assert.Equal(providers, collection.ToArray());
}
[Fact]
public void DefaultConstructor()
{
// Act
ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
// Assert
Assert.Empty(collection);
}
[Fact]
public void AddNullProviderThrows()
{
// Arrange
ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
// Act & Assert
Assert.ThrowsArgumentNull(
delegate { collection.Add(null); },
"item");
}
[Fact]
public void RegisterBinderForGenericType_Factory()
{
// Arrange
ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
ModelBinderProviderCollection collection = new ModelBinderProviderCollection
{
mockProvider
};
// Act
collection.RegisterBinderForGenericType(typeof(List<>), _ => mockBinder);
// Assert
var genericProvider = Assert.IsType<GenericModelBinderProvider>(collection[0]);
Assert.Equal(typeof(List<>), genericProvider.ModelType);
Assert.Equal(mockProvider, collection[1]);
}
[Fact]
public void RegisterBinderForGenericType_Instance()
{
// Arrange
ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
ModelBinderProviderCollection collection = new ModelBinderProviderCollection
{
mockProvider
};
// Act
collection.RegisterBinderForGenericType(typeof(List<>), mockBinder);
// Assert
var genericProvider = Assert.IsType<GenericModelBinderProvider>(collection[0]);
Assert.Equal(typeof(List<>), genericProvider.ModelType);
Assert.Equal(mockProvider, collection[1]);
}
[Fact]
public void RegisterBinderForGenericType_Type()
{
// Arrange
ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
ModelBinderProviderCollection collection = new ModelBinderProviderCollection
{
mockProvider
};
// Act
collection.RegisterBinderForGenericType(typeof(List<>), typeof(CollectionModelBinder<>));
// Assert
var genericProvider = Assert.IsType<GenericModelBinderProvider>(collection[0]);
Assert.Equal(typeof(List<>), genericProvider.ModelType);
Assert.Equal(mockProvider, collection[1]);
}
[Fact]
public void RegisterBinderForType_Factory()
{
// Arrange
ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
ModelBinderProviderCollection collection = new ModelBinderProviderCollection
{
mockProvider
};
// Act
collection.RegisterBinderForType(typeof(int), () => mockBinder);
// Assert
var simpleProvider = Assert.IsType<SimpleModelBinderProvider>(collection[0]);
Assert.Equal(typeof(int), simpleProvider.ModelType);
Assert.Equal(mockProvider, collection[1]);
}
[Fact]
public void RegisterBinderForType_Instance()
{
// Arrange
ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
ModelBinderProviderCollection collection = new ModelBinderProviderCollection
{
mockProvider
};
// Act
collection.RegisterBinderForType(typeof(int), mockBinder);
// Assert
var simpleProvider = Assert.IsType<SimpleModelBinderProvider>(collection[0]);
Assert.Equal(typeof(int), simpleProvider.ModelType);
Assert.Equal(mockProvider, collection[1]);
}
[Fact]
public void RegisterBinderForType_Instance_InsertsNewProviderBehindFrontOfListProviders()
{
// Arrange
ModelBinderProvider frontOfListProvider = new ProviderAtFront();
IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
ModelBinderProviderCollection collection = new ModelBinderProviderCollection
{
frontOfListProvider
};
// Act
collection.RegisterBinderForType(typeof(int), mockBinder);
// Assert
Assert.Equal(
new[] { typeof(ProviderAtFront), typeof(SimpleModelBinderProvider) },
collection.Select(o => o.GetType()).ToArray());
}
[Fact]
public void SetItem()
{
// Arrange
ModelBinderProvider provider0 = new Mock<ModelBinderProvider>().Object;
ModelBinderProvider provider1 = new Mock<ModelBinderProvider>().Object;
ModelBinderProvider provider2 = new Mock<ModelBinderProvider>().Object;
ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
collection.Add(provider0);
collection.Add(provider1);
// Act
collection[1] = provider2;
// Assert
Assert.Equal(new[] { provider0, provider2 }, collection.ToArray());
}
[Fact]
public void SetNullProviderThrows()
{
// Arrange
ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
collection.Add(new Mock<ModelBinderProvider>().Object);
// Act & Assert
Assert.ThrowsArgumentNull(
delegate { collection[0] = null; },
"item");
}
[Fact]
public void GetBinder_FromAttribute_BadAttribute_Throws()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_BadAttribute))
};
ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
// Act & assert
Assert.Throws<InvalidOperationException>(
delegate { providers.GetBinder(controllerContext, bindingContext); },
@"The type 'System.Object' does not subclass Microsoft.Web.Mvc.ModelBinding.ModelBinderProvider or implement the interface Microsoft.Web.Mvc.ModelBinding.IExtensibleModelBinder.");
}
[Fact]
public void GetBinder_FromAttribute_Binder_Generic_ReturnsBinder()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder_Generic<int>)),
ModelName = "foo",
ValueProvider = new SimpleValueProvider
{
{ "foo", "fooValue" }
}
};
ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder_Generic<int>), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
// Act
IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
// Assert
Assert.IsType<CustomGenericBinder<int>>(binder);
}
[Fact]
public void GetBinder_FromAttribute_Binder_SuppressPrefixCheck_ReturnsBinder()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder_SuppressPrefix)),
ModelName = "foo",
ValueProvider = new SimpleValueProvider
{
{ "bar", "barValue" }
}
};
ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder_SuppressPrefix), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
// Act
IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
// Assert
Assert.IsType<CustomBinder>(binder);
}
[Fact]
public void GetBinder_FromAttribute_Binder_ValueNotPresent_ReturnsNull()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder)),
ModelName = "foo",
ValueProvider = new SimpleValueProvider
{
{ "bar", "barValue" }
}
};
ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
// Act
IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
// Assert
Assert.Null(binder);
}
[Fact]
public void GetBinder_FromAttribute_Binder_ValuePresent_ReturnsBinder()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder)),
ModelName = "foo",
ValueProvider = new SimpleValueProvider
{
{ "foo", "fooValue" }
}
};
ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
// Act
IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
// Assert
Assert.IsType<CustomBinder>(binder);
}
[Fact]
public void GetBinder_FromAttribute_Provider_ReturnsBinder()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Provider))
};
ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Provider), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
// Act
IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
// Assert
Assert.IsType<CustomBinder>(binder);
}
[Fact]
public void GetBinderReturnsFirstBinderFromProviders()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object))
};
IExtensibleModelBinder expectedBinder = new Mock<IExtensibleModelBinder>().Object;
Mock<ModelBinderProvider> mockProvider = new Mock<ModelBinderProvider>();
mockProvider.Setup(p => p.GetBinder(controllerContext, bindingContext)).Returns(expectedBinder);
ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new[]
{
new Mock<ModelBinderProvider>().Object,
mockProvider.Object,
new Mock<ModelBinderProvider>().Object
});
// Act
IExtensibleModelBinder returned = collection.GetBinder(controllerContext, bindingContext);
// Assert
Assert.Equal(expectedBinder, returned);
}
[Fact]
public void GetBinderReturnsNullIfNoProviderMatches()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object))
};
ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new[]
{
new Mock<ModelBinderProvider>().Object,
});
// Act
IExtensibleModelBinder returned = collection.GetBinder(controllerContext, bindingContext);
// Assert
Assert.Null(returned);
}
[Fact]
public void GetBinderThrowsIfBindingContextIsNull()
{
// Arrange
ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
// Act & assert
Assert.ThrowsArgumentNull(
delegate { collection.GetBinder(new ControllerContext(), null); }, "bindingContext");
}
[Fact]
public void GetBinderThrowsIfControllerContextIsNull()
{
// Arrange
ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
// Act & assert
Assert.ThrowsArgumentNull(
delegate { collection.GetBinder(null, new ExtensibleModelBindingContext()); }, "controllerContext");
}
[Fact]
public void GetBinderThrowsIfModelTypeHasBindAttribute()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithBindAttribute))
};
ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
// Act & assert
Assert.Throws<InvalidOperationException>(
delegate { collection.GetBinder(controllerContext, bindingContext); },
@"The model of type 'Microsoft.Web.Mvc.ModelBinding.Test.ModelBinderProviderCollectionTest+ModelWithBindAttribute' has a [Bind] attribute. The new model binding system cannot be used with models that have type-level [Bind] attributes. Use the [BindRequired] and [BindNever] attributes on the model type or its properties instead.");
}
[Fact]
public void GetRequiredBinderThrowsIfNoProviderMatches()
{
// Arrange
ControllerContext controllerContext = new ControllerContext();
ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int))
};
ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new[]
{
new Mock<ModelBinderProvider>().Object,
});
// Act & assert
Assert.Throws<InvalidOperationException>(
delegate { collection.GetRequiredBinder(controllerContext, bindingContext); },
@"A binder for type System.Int32 could not be located.");
}
[MetadataType(typeof(ModelWithBindAttribute_Buddy))]
private class ModelWithBindAttribute
{
[Bind]
private class ModelWithBindAttribute_Buddy
{
}
}
[ModelBinderProviderOptions(FrontOfList = true)]
private class ProviderAtFront : ModelBinderProvider
{
public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
{
throw new NotImplementedException();
}
}
[ExtensibleModelBinder(typeof(object))]
private class ModelWithProviderAttribute_BadAttribute
{
}
[ExtensibleModelBinder(typeof(CustomBinder))]
private class ModelWithProviderAttribute_Binder
{
}
[ExtensibleModelBinder(typeof(CustomGenericBinder<>))]
private class ModelWithProviderAttribute_Binder_Generic<T>
{
}
[ExtensibleModelBinder(typeof(CustomBinder), SuppressPrefixCheck = true)]
private class ModelWithProviderAttribute_Binder_SuppressPrefix
{
}
[ExtensibleModelBinder(typeof(CustomProvider))]
private class ModelWithProviderAttribute_Provider
{
}
private class CustomProvider : ModelBinderProvider
{
public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
{
return new CustomBinder();
}
}
private class CustomBinder : IExtensibleModelBinder
{
public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
{
throw new NotImplementedException();
}
}
private class CustomGenericBinder<T> : IExtensibleModelBinder
{
public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
{
throw new NotImplementedException();
}
}
}
}