PageRenderTime 21ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/test/Microsoft.Web.Mvc.Test/ModelBinding/Test/ModelBinderProviderCollectionTest.cs

https://bitbucket.org/mdavid/aspnetwebstack
C# | 527 lines | 378 code | 88 blank | 61 comment | 0 complexity | 9d4a1cc2aa70bedd6007d5946adc6d2f MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.DataAnnotations;
  4. using System.Linq;
  5. using System.Web.Mvc;
  6. using Microsoft.Web.UnitTestUtil;
  7. using Moq;
  8. using Xunit;
  9. using Assert = Microsoft.TestCommon.AssertEx;
  10. namespace Microsoft.Web.Mvc.ModelBinding.Test
  11. {
  12. public class ModelBinderProviderCollectionTest
  13. {
  14. [Fact]
  15. public void ListWrappingConstructor()
  16. {
  17. // Arrange
  18. ModelBinderProvider[] providers = new[]
  19. {
  20. new Mock<ModelBinderProvider>().Object,
  21. new Mock<ModelBinderProvider>().Object
  22. };
  23. // Act
  24. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(providers);
  25. // Assert
  26. Assert.Equal(providers, collection.ToArray());
  27. }
  28. [Fact]
  29. public void DefaultConstructor()
  30. {
  31. // Act
  32. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  33. // Assert
  34. Assert.Empty(collection);
  35. }
  36. [Fact]
  37. public void AddNullProviderThrows()
  38. {
  39. // Arrange
  40. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  41. // Act & Assert
  42. Assert.ThrowsArgumentNull(
  43. delegate { collection.Add(null); },
  44. "item");
  45. }
  46. [Fact]
  47. public void RegisterBinderForGenericType_Factory()
  48. {
  49. // Arrange
  50. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  51. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  52. ModelBinderProviderCollection collection = new ModelBinderProviderCollection
  53. {
  54. mockProvider
  55. };
  56. // Act
  57. collection.RegisterBinderForGenericType(typeof(List<>), _ => mockBinder);
  58. // Assert
  59. var genericProvider = Assert.IsType<GenericModelBinderProvider>(collection[0]);
  60. Assert.Equal(typeof(List<>), genericProvider.ModelType);
  61. Assert.Equal(mockProvider, collection[1]);
  62. }
  63. [Fact]
  64. public void RegisterBinderForGenericType_Instance()
  65. {
  66. // Arrange
  67. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  68. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  69. ModelBinderProviderCollection collection = new ModelBinderProviderCollection
  70. {
  71. mockProvider
  72. };
  73. // Act
  74. collection.RegisterBinderForGenericType(typeof(List<>), mockBinder);
  75. // Assert
  76. var genericProvider = Assert.IsType<GenericModelBinderProvider>(collection[0]);
  77. Assert.Equal(typeof(List<>), genericProvider.ModelType);
  78. Assert.Equal(mockProvider, collection[1]);
  79. }
  80. [Fact]
  81. public void RegisterBinderForGenericType_Type()
  82. {
  83. // Arrange
  84. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  85. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  86. ModelBinderProviderCollection collection = new ModelBinderProviderCollection
  87. {
  88. mockProvider
  89. };
  90. // Act
  91. collection.RegisterBinderForGenericType(typeof(List<>), typeof(CollectionModelBinder<>));
  92. // Assert
  93. var genericProvider = Assert.IsType<GenericModelBinderProvider>(collection[0]);
  94. Assert.Equal(typeof(List<>), genericProvider.ModelType);
  95. Assert.Equal(mockProvider, collection[1]);
  96. }
  97. [Fact]
  98. public void RegisterBinderForType_Factory()
  99. {
  100. // Arrange
  101. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  102. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  103. ModelBinderProviderCollection collection = new ModelBinderProviderCollection
  104. {
  105. mockProvider
  106. };
  107. // Act
  108. collection.RegisterBinderForType(typeof(int), () => mockBinder);
  109. // Assert
  110. var simpleProvider = Assert.IsType<SimpleModelBinderProvider>(collection[0]);
  111. Assert.Equal(typeof(int), simpleProvider.ModelType);
  112. Assert.Equal(mockProvider, collection[1]);
  113. }
  114. [Fact]
  115. public void RegisterBinderForType_Instance()
  116. {
  117. // Arrange
  118. ModelBinderProvider mockProvider = new Mock<ModelBinderProvider>().Object;
  119. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  120. ModelBinderProviderCollection collection = new ModelBinderProviderCollection
  121. {
  122. mockProvider
  123. };
  124. // Act
  125. collection.RegisterBinderForType(typeof(int), mockBinder);
  126. // Assert
  127. var simpleProvider = Assert.IsType<SimpleModelBinderProvider>(collection[0]);
  128. Assert.Equal(typeof(int), simpleProvider.ModelType);
  129. Assert.Equal(mockProvider, collection[1]);
  130. }
  131. [Fact]
  132. public void RegisterBinderForType_Instance_InsertsNewProviderBehindFrontOfListProviders()
  133. {
  134. // Arrange
  135. ModelBinderProvider frontOfListProvider = new ProviderAtFront();
  136. IExtensibleModelBinder mockBinder = new Mock<IExtensibleModelBinder>().Object;
  137. ModelBinderProviderCollection collection = new ModelBinderProviderCollection
  138. {
  139. frontOfListProvider
  140. };
  141. // Act
  142. collection.RegisterBinderForType(typeof(int), mockBinder);
  143. // Assert
  144. Assert.Equal(
  145. new[] { typeof(ProviderAtFront), typeof(SimpleModelBinderProvider) },
  146. collection.Select(o => o.GetType()).ToArray());
  147. }
  148. [Fact]
  149. public void SetItem()
  150. {
  151. // Arrange
  152. ModelBinderProvider provider0 = new Mock<ModelBinderProvider>().Object;
  153. ModelBinderProvider provider1 = new Mock<ModelBinderProvider>().Object;
  154. ModelBinderProvider provider2 = new Mock<ModelBinderProvider>().Object;
  155. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  156. collection.Add(provider0);
  157. collection.Add(provider1);
  158. // Act
  159. collection[1] = provider2;
  160. // Assert
  161. Assert.Equal(new[] { provider0, provider2 }, collection.ToArray());
  162. }
  163. [Fact]
  164. public void SetNullProviderThrows()
  165. {
  166. // Arrange
  167. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  168. collection.Add(new Mock<ModelBinderProvider>().Object);
  169. // Act & Assert
  170. Assert.ThrowsArgumentNull(
  171. delegate { collection[0] = null; },
  172. "item");
  173. }
  174. [Fact]
  175. public void GetBinder_FromAttribute_BadAttribute_Throws()
  176. {
  177. // Arrange
  178. ControllerContext controllerContext = new ControllerContext();
  179. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  180. {
  181. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_BadAttribute))
  182. };
  183. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  184. // Act & assert
  185. Assert.Throws<InvalidOperationException>(
  186. delegate { providers.GetBinder(controllerContext, bindingContext); },
  187. @"The type 'System.Object' does not subclass Microsoft.Web.Mvc.ModelBinding.ModelBinderProvider or implement the interface Microsoft.Web.Mvc.ModelBinding.IExtensibleModelBinder.");
  188. }
  189. [Fact]
  190. public void GetBinder_FromAttribute_Binder_Generic_ReturnsBinder()
  191. {
  192. // Arrange
  193. ControllerContext controllerContext = new ControllerContext();
  194. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  195. {
  196. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder_Generic<int>)),
  197. ModelName = "foo",
  198. ValueProvider = new SimpleValueProvider
  199. {
  200. { "foo", "fooValue" }
  201. }
  202. };
  203. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  204. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder_Generic<int>), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  205. // Act
  206. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  207. // Assert
  208. Assert.IsType<CustomGenericBinder<int>>(binder);
  209. }
  210. [Fact]
  211. public void GetBinder_FromAttribute_Binder_SuppressPrefixCheck_ReturnsBinder()
  212. {
  213. // Arrange
  214. ControllerContext controllerContext = new ControllerContext();
  215. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  216. {
  217. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder_SuppressPrefix)),
  218. ModelName = "foo",
  219. ValueProvider = new SimpleValueProvider
  220. {
  221. { "bar", "barValue" }
  222. }
  223. };
  224. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  225. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder_SuppressPrefix), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  226. // Act
  227. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  228. // Assert
  229. Assert.IsType<CustomBinder>(binder);
  230. }
  231. [Fact]
  232. public void GetBinder_FromAttribute_Binder_ValueNotPresent_ReturnsNull()
  233. {
  234. // Arrange
  235. ControllerContext controllerContext = new ControllerContext();
  236. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  237. {
  238. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder)),
  239. ModelName = "foo",
  240. ValueProvider = new SimpleValueProvider
  241. {
  242. { "bar", "barValue" }
  243. }
  244. };
  245. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  246. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  247. // Act
  248. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  249. // Assert
  250. Assert.Null(binder);
  251. }
  252. [Fact]
  253. public void GetBinder_FromAttribute_Binder_ValuePresent_ReturnsBinder()
  254. {
  255. // Arrange
  256. ControllerContext controllerContext = new ControllerContext();
  257. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  258. {
  259. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Binder)),
  260. ModelName = "foo",
  261. ValueProvider = new SimpleValueProvider
  262. {
  263. { "foo", "fooValue" }
  264. }
  265. };
  266. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  267. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Binder), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  268. // Act
  269. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  270. // Assert
  271. Assert.IsType<CustomBinder>(binder);
  272. }
  273. [Fact]
  274. public void GetBinder_FromAttribute_Provider_ReturnsBinder()
  275. {
  276. // Arrange
  277. ControllerContext controllerContext = new ControllerContext();
  278. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  279. {
  280. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithProviderAttribute_Provider))
  281. };
  282. ModelBinderProviderCollection providers = new ModelBinderProviderCollection();
  283. providers.RegisterBinderForType(typeof(ModelWithProviderAttribute_Provider), new Mock<IExtensibleModelBinder>().Object, true /* suppressPrefix */);
  284. // Act
  285. IExtensibleModelBinder binder = providers.GetBinder(controllerContext, bindingContext);
  286. // Assert
  287. Assert.IsType<CustomBinder>(binder);
  288. }
  289. [Fact]
  290. public void GetBinderReturnsFirstBinderFromProviders()
  291. {
  292. // Arrange
  293. ControllerContext controllerContext = new ControllerContext();
  294. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  295. {
  296. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object))
  297. };
  298. IExtensibleModelBinder expectedBinder = new Mock<IExtensibleModelBinder>().Object;
  299. Mock<ModelBinderProvider> mockProvider = new Mock<ModelBinderProvider>();
  300. mockProvider.Setup(p => p.GetBinder(controllerContext, bindingContext)).Returns(expectedBinder);
  301. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new[]
  302. {
  303. new Mock<ModelBinderProvider>().Object,
  304. mockProvider.Object,
  305. new Mock<ModelBinderProvider>().Object
  306. });
  307. // Act
  308. IExtensibleModelBinder returned = collection.GetBinder(controllerContext, bindingContext);
  309. // Assert
  310. Assert.Equal(expectedBinder, returned);
  311. }
  312. [Fact]
  313. public void GetBinderReturnsNullIfNoProviderMatches()
  314. {
  315. // Arrange
  316. ControllerContext controllerContext = new ControllerContext();
  317. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  318. {
  319. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(object))
  320. };
  321. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new[]
  322. {
  323. new Mock<ModelBinderProvider>().Object,
  324. });
  325. // Act
  326. IExtensibleModelBinder returned = collection.GetBinder(controllerContext, bindingContext);
  327. // Assert
  328. Assert.Null(returned);
  329. }
  330. [Fact]
  331. public void GetBinderThrowsIfBindingContextIsNull()
  332. {
  333. // Arrange
  334. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  335. // Act & assert
  336. Assert.ThrowsArgumentNull(
  337. delegate { collection.GetBinder(new ControllerContext(), null); }, "bindingContext");
  338. }
  339. [Fact]
  340. public void GetBinderThrowsIfControllerContextIsNull()
  341. {
  342. // Arrange
  343. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  344. // Act & assert
  345. Assert.ThrowsArgumentNull(
  346. delegate { collection.GetBinder(null, new ExtensibleModelBindingContext()); }, "controllerContext");
  347. }
  348. [Fact]
  349. public void GetBinderThrowsIfModelTypeHasBindAttribute()
  350. {
  351. // Arrange
  352. ControllerContext controllerContext = new ControllerContext();
  353. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  354. {
  355. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(ModelWithBindAttribute))
  356. };
  357. ModelBinderProviderCollection collection = new ModelBinderProviderCollection();
  358. // Act & assert
  359. Assert.Throws<InvalidOperationException>(
  360. delegate { collection.GetBinder(controllerContext, bindingContext); },
  361. @"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.");
  362. }
  363. [Fact]
  364. public void GetRequiredBinderThrowsIfNoProviderMatches()
  365. {
  366. // Arrange
  367. ControllerContext controllerContext = new ControllerContext();
  368. ExtensibleModelBindingContext bindingContext = new ExtensibleModelBindingContext
  369. {
  370. ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int))
  371. };
  372. ModelBinderProviderCollection collection = new ModelBinderProviderCollection(new[]
  373. {
  374. new Mock<ModelBinderProvider>().Object,
  375. });
  376. // Act & assert
  377. Assert.Throws<InvalidOperationException>(
  378. delegate { collection.GetRequiredBinder(controllerContext, bindingContext); },
  379. @"A binder for type System.Int32 could not be located.");
  380. }
  381. [MetadataType(typeof(ModelWithBindAttribute_Buddy))]
  382. private class ModelWithBindAttribute
  383. {
  384. [Bind]
  385. private class ModelWithBindAttribute_Buddy
  386. {
  387. }
  388. }
  389. [ModelBinderProviderOptions(FrontOfList = true)]
  390. private class ProviderAtFront : ModelBinderProvider
  391. {
  392. public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
  393. {
  394. throw new NotImplementedException();
  395. }
  396. }
  397. [ExtensibleModelBinder(typeof(object))]
  398. private class ModelWithProviderAttribute_BadAttribute
  399. {
  400. }
  401. [ExtensibleModelBinder(typeof(CustomBinder))]
  402. private class ModelWithProviderAttribute_Binder
  403. {
  404. }
  405. [ExtensibleModelBinder(typeof(CustomGenericBinder<>))]
  406. private class ModelWithProviderAttribute_Binder_Generic<T>
  407. {
  408. }
  409. [ExtensibleModelBinder(typeof(CustomBinder), SuppressPrefixCheck = true)]
  410. private class ModelWithProviderAttribute_Binder_SuppressPrefix
  411. {
  412. }
  413. [ExtensibleModelBinder(typeof(CustomProvider))]
  414. private class ModelWithProviderAttribute_Provider
  415. {
  416. }
  417. private class CustomProvider : ModelBinderProvider
  418. {
  419. public override IExtensibleModelBinder GetBinder(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
  420. {
  421. return new CustomBinder();
  422. }
  423. }
  424. private class CustomBinder : IExtensibleModelBinder
  425. {
  426. public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
  427. {
  428. throw new NotImplementedException();
  429. }
  430. }
  431. private class CustomGenericBinder<T> : IExtensibleModelBinder
  432. {
  433. public bool BindModel(ControllerContext controllerContext, ExtensibleModelBindingContext bindingContext)
  434. {
  435. throw new NotImplementedException();
  436. }
  437. }
  438. }
  439. }