/src/UnitTests/IOC/Configuration/LoaderAttributeTests.cs

http://github.com/philiplaureano/LinFu · C# · 319 lines · 220 code · 71 blank · 28 comment · 8 complexity · 7d2573731febf6cc7385f370e935f82b MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using LinFu.IoC;
  6. using LinFu.IoC.Configuration;
  7. using LinFu.IoC.Configuration.Loaders;
  8. using LinFu.IoC.Factories;
  9. using LinFu.IoC.Interfaces;
  10. using Moq;
  11. using Xunit;
  12. using SampleLibrary;
  13. namespace LinFu.UnitTests.IOC.Configuration
  14. {
  15. public class LoaderAttributeTests
  16. {
  17. private static void TestFactoryConverterWith<TFactory>(string serviceName, Type serviceType,
  18. Type implementingType, ITypeLoader loader)
  19. where TFactory : IFactory
  20. {
  21. // The loader should initialize the container with
  22. // the particular factory type
  23. var mockContainer = new Mock<IServiceContainer>();
  24. mockContainer.Expect(container =>
  25. container.AddFactory(serviceName, serviceType, It.IsAny<IEnumerable<Type>>(),
  26. It.Is<IFactory>(
  27. f => f != null && f is TFactory || f is FunctorFactory)));
  28. var factoryActions = loader.Load(implementingType).ToArray();
  29. Assert.NotNull(factoryActions);
  30. Assert.True(factoryActions.Count() == 1);
  31. // There must be at least one factory from
  32. // the result list
  33. var firstResult = factoryActions.FirstOrDefault();
  34. Assert.NotNull(firstResult);
  35. firstResult(mockContainer.Object);
  36. mockContainer.VerifyAll();
  37. }
  38. [Fact]
  39. public void FactoryAttributeLoaderMustInjectOpenGenericServiceTypeIntoContainer()
  40. {
  41. var mockContainer = new Mock<IServiceContainer>();
  42. var serviceType = typeof(ISampleGenericService<>);
  43. var mockPostProcessors = new Mock<IList<IPostProcessor>>();
  44. var mockPreProcessors = new Mock<IList<IPreProcessor>>();
  45. ITypeLoader loader = new FactoryAttributeLoader();
  46. var actions = loader.Load(typeof(SampleOpenGenericFactory));
  47. // The loader should load the mock container
  48. // using the generic open type as the service type
  49. mockContainer.Expect(container => container.PostProcessors)
  50. .Returns(mockPostProcessors.Object);
  51. mockContainer.Expect(container => container.PreProcessors)
  52. .Returns(mockPreProcessors.Object);
  53. mockContainer.Expect(container => container.AddFactory(null,
  54. serviceType, It.IsAny<IEnumerable<Type>>(),
  55. It.IsAny<SampleOpenGenericFactory>()));
  56. // The postprocessor list should have an additional element added
  57. mockPostProcessors.Expect(p => p.Add(It.IsAny<IPostProcessor>()));
  58. // The preprocessor list should have an additional element added as well
  59. mockPreProcessors.Expect(p => p.Add(It.IsAny<IPreProcessor>()));
  60. Action<IServiceContainer> applyActions =
  61. container =>
  62. {
  63. foreach (var action in actions) action(container);
  64. };
  65. applyActions(mockContainer.Object);
  66. // Apply the actions to a real container and verify
  67. // it with the expected service instance
  68. var realContainer = new ServiceContainer();
  69. applyActions(realContainer);
  70. }
  71. [Fact]
  72. public void FactoryAttributeLoaderMustInjectStronglyTypedFactoryIntoContainer()
  73. {
  74. var container = new ServiceContainer();
  75. var serviceType = typeof(ISampleService);
  76. ITypeLoader loader = new FactoryAttributeLoader();
  77. var actions = loader.Load(typeof(SampleStronglyTypedFactory));
  78. // The factory loader should return a set of actions
  79. // that will inject that custom factory into the container
  80. // itself
  81. foreach (var action in actions) action(container);
  82. Assert.True(container.Contains(serviceType));
  83. }
  84. [Fact]
  85. public void FactoryAttributeLoaderMustInjectUnnamedCustomFactoryIntoContainer()
  86. {
  87. var mockContainer = new Mock<IServiceContainer>();
  88. var mockPreProcessors = new Mock<IList<IPreProcessor>>();
  89. var serviceType = typeof(ISampleService);
  90. string serviceName = null;
  91. // The container should add the expected
  92. // factory type
  93. mockContainer.Expect(
  94. container => container.AddFactory(serviceName, serviceType, It.IsAny<IEnumerable<Type>>(),
  95. It.IsAny<SampleFactory>()));
  96. // The factory attribute loader will add the custom
  97. // factory to the preprocessors collection
  98. mockContainer.Expect(container => container.PreProcessors)
  99. .Returns(mockPreProcessors.Object);
  100. mockPreProcessors.Expect(p => p.Add(It.IsAny<IPreProcessor>()));
  101. ITypeLoader loader = new FactoryAttributeLoader();
  102. var actions = loader.Load(typeof(SampleFactory));
  103. // The factory loader should return a set of actions
  104. // that will inject that custom factory into the container
  105. // itself
  106. foreach (var action in actions) action(mockContainer.Object);
  107. mockContainer.VerifyAll();
  108. }
  109. [Fact]
  110. public void LoaderMustLoadSingletonTypesAndThoseTypesMustBeTheSameInstance()
  111. {
  112. var location = typeof(SamplePostProcessor).Assembly.Location ?? string.Empty;
  113. var loader = new Loader();
  114. var directory = Path.GetDirectoryName(location);
  115. // Load the default plugins first
  116. loader.LoadDirectory(AppDomain.CurrentDomain.BaseDirectory, "LinFu*.dll");
  117. // Load the sample library
  118. loader.LoadDirectory(directory, Path.GetFileName(location));
  119. var filename = Path.Combine(directory, location);
  120. Assert.True(File.Exists(filename));
  121. var container = new ServiceContainer();
  122. loader.LoadInto(container);
  123. var first = container.GetService<ISampleService>("First");
  124. var second = container.GetService<ISampleService>("First");
  125. Assert.NotNull(first);
  126. Assert.NotNull(second);
  127. Assert.Same(first, second);
  128. }
  129. [Fact]
  130. public void LoaderMustLoadTheCorrectOncePerRequestTypes()
  131. {
  132. var location = typeof(SamplePostProcessor).Assembly.Location ?? string.Empty;
  133. var loader = new Loader();
  134. var directory = Path.GetDirectoryName(location);
  135. // Load the default plugins first
  136. loader.LoadDirectory(AppDomain.CurrentDomain.BaseDirectory, "LinFu*.dll");
  137. // Load the sample library
  138. loader.LoadDirectory(directory, Path.GetFileName(location));
  139. var filename = Path.Combine(directory, location);
  140. Assert.True(File.Exists(filename));
  141. var container = new ServiceContainer();
  142. loader.LoadInto(container);
  143. var first = container.GetService<ISampleService>("FirstOncePerRequestService");
  144. var second = container.GetService<ISampleService>("SecondOncePerRequestService");
  145. Assert.NotNull(first);
  146. Assert.NotNull(second);
  147. Assert.True(first.GetType() == typeof(FirstOncePerRequestService));
  148. Assert.True(second.GetType() == typeof(SecondOncePerRequestService));
  149. }
  150. [Fact]
  151. public void LoaderMustLoadTheCorrectSingletonTypes()
  152. {
  153. var location = typeof(SamplePostProcessor).Assembly.Location ?? string.Empty;
  154. var loader = new Loader();
  155. var directory = Path.GetDirectoryName(location);
  156. // Load the default plugins first
  157. loader.LoadDirectory(AppDomain.CurrentDomain.BaseDirectory, "LinFu*.dll");
  158. // Load the sample library
  159. loader.LoadDirectory(directory, Path.GetFileName(location));
  160. var filename = Path.Combine(directory, location);
  161. Assert.True(File.Exists(filename));
  162. var container = new ServiceContainer();
  163. loader.LoadInto(container);
  164. var first = container.GetService<ISampleService>("First");
  165. var second = container.GetService<ISampleService>("Second");
  166. Assert.NotNull(first);
  167. Assert.NotNull(second);
  168. Assert.True(first.GetType() == typeof(FirstSingletonService));
  169. Assert.True(second.GetType() == typeof(SecondSingletonService));
  170. }
  171. [Fact]
  172. public void NamedOncePerRequestFactoryMustBeCreatedFromTypeWithImplementsAttribute()
  173. {
  174. var implementingType = typeof(NamedOncePerRequestSampleService);
  175. var serviceType = typeof(ISampleService);
  176. var converter = new ImplementsAttributeLoader();
  177. TestFactoryConverterWith<OncePerRequestFactory<ISampleService>>("MyService",
  178. serviceType, implementingType, converter);
  179. }
  180. [Fact]
  181. public void NamedOncePerThreadFactoryMustBeCreatedFromTypeWithImplementsAttribute()
  182. {
  183. TestFactoryConverterWith<OncePerThreadFactory<ISampleService>>("MyService",
  184. typeof(ISampleService),
  185. typeof(NamedOncePerThreadSampleService),
  186. new ImplementsAttributeLoader());
  187. }
  188. [Fact]
  189. public void NamedSingletonFactoryMustBeCreatedFromTypeWithImplementsAttribute()
  190. {
  191. TestFactoryConverterWith<SingletonFactory<ISampleService>>("MyService",
  192. typeof(ISampleService),
  193. typeof(NamedSingletonSampleService),
  194. new ImplementsAttributeLoader());
  195. }
  196. [Fact]
  197. public void OncePerRequestFactoryMustBeCreatedFromTypeWithImplementsAttribute()
  198. {
  199. var implementingType = typeof(OncePerRequestSampleService);
  200. var serviceType = typeof(ISampleService);
  201. var converter = new ImplementsAttributeLoader();
  202. TestFactoryConverterWith<OncePerRequestFactory<ISampleService>>(null,
  203. serviceType, implementingType, converter);
  204. }
  205. [Fact]
  206. public void OncePerThreadFactoryMustBeCreatedFromTypeWithImplementsAttribute()
  207. {
  208. TestFactoryConverterWith<OncePerThreadFactory<ISampleService>>(null,
  209. typeof(ISampleService),
  210. typeof(OncePerThreadSampleService),
  211. new ImplementsAttributeLoader());
  212. }
  213. [Fact]
  214. public void ServicesCreatedFromCustomOpenGenericFactoryMustInvokeIInitialize()
  215. {
  216. var mockFactory = new Mock<IFactory>();
  217. var serviceInstance = new SampleGenericImplementation<int>();
  218. mockFactory.Expect(f => f.CreateInstance(It.IsAny<IFactoryRequest>()))
  219. .Returns(serviceInstance);
  220. var container = new ServiceContainer();
  221. container.LoadFrom(AppDomain.CurrentDomain.BaseDirectory, "LinFu*.dll");
  222. container.AddFactory("MyService", typeof(ISampleGenericService<>), mockFactory.Object);
  223. var result = container.GetService<ISampleGenericService<int>>("MyService");
  224. var areSame = ReferenceEquals(serviceInstance, result);
  225. Assert.Same(serviceInstance, result);
  226. // Make sure that the IInitialize instance is called
  227. // on the sample class
  228. Assert.True(serviceInstance.Called);
  229. mockFactory.VerifyAll();
  230. }
  231. [Fact]
  232. public void ShouldInjectInternallyVisibleServiceTypeMarkedWithImplementsAttribute()
  233. {
  234. var container = new ServiceContainer();
  235. container.LoadFromBaseDirectory("*.dll");
  236. var service = container.GetService<ISampleService>("internal");
  237. Assert.NotNull(service);
  238. }
  239. [Fact]
  240. public void SingletonFactoryMustBeCreatedFromTypeWithImplementsAttribute()
  241. {
  242. TestFactoryConverterWith<SingletonFactory<ISampleService>>(null,
  243. typeof(ISampleService),
  244. typeof(SingletonSampleService),
  245. new ImplementsAttributeLoader());
  246. }
  247. }
  248. }