/src/UnitTests/IOC/ResolutionTests.cs

http://github.com/philiplaureano/LinFu · C# · 358 lines · 270 code · 72 blank · 16 comment · 4 complexity · 9fdfd7e98162271f8549c9b4300154fb MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using LinFu.IoC;
  6. using LinFu.IoC.Configuration;
  7. using LinFu.IoC.Configuration.Interfaces;
  8. using LinFu.IoC.Interfaces;
  9. using Moq;
  10. using Xunit;
  11. using SampleLibrary;
  12. using SampleLibrary.IOC;
  13. namespace LinFu.UnitTests.IOC
  14. {
  15. public class ResolutionTests
  16. {
  17. private static ServiceContainer GetContainerWithMockSampleServices()
  18. {
  19. var mockSampleService = new Mock<ISampleService>();
  20. var container = new ServiceContainer();
  21. // Add a bunch of dummy services
  22. for (var i = 0; i < 10; i++)
  23. {
  24. var serviceName = string.Format("Service{0}", i + 1);
  25. container.AddService(serviceName, mockSampleService.Object);
  26. }
  27. var services = container.GetServices<ISampleService>();
  28. Assert.True(services.Count() == 10);
  29. foreach (var service in services) Assert.Same(mockSampleService.Object, service);
  30. return container;
  31. }
  32. [Fact]
  33. public void ShouldAutoCreateClassWithServiceArrayAsConstructorArgument()
  34. {
  35. var container = GetContainerWithMockSampleServices();
  36. var result = container.AutoCreate(typeof(SampleClassWithServiceArrayAsConstructorArgument))
  37. as SampleClassWithServiceArrayAsConstructorArgument;
  38. Assert.NotNull(result);
  39. Assert.True(result.Services.Length > 0);
  40. }
  41. [Fact]
  42. public void ShouldAutoCreateClassWithServiceEnumerableAsConstructorArgument()
  43. {
  44. var container = GetContainerWithMockSampleServices();
  45. var result = container.AutoCreate(typeof(SampleClassWithServiceEnumerableAsConstructorArgument))
  46. as SampleClassWithServiceEnumerableAsConstructorArgument;
  47. Assert.NotNull(result);
  48. Assert.NotNull(result.Services);
  49. Assert.True(result.Services.Count() > 0);
  50. }
  51. [Fact]
  52. public void ShouldBeAbleToAutoCreateClassUsingGenericAutoCreateCall()
  53. {
  54. var container = GetContainerWithMockSampleServices();
  55. var result = container.AutoCreate<SampleClassWithServiceArrayAsConstructorArgument>();
  56. Assert.NotNull(result);
  57. Assert.True(result.Services.Length > 0);
  58. }
  59. [Fact]
  60. public void ShouldCallStronglyTypedFunctorInsteadOfActualFactory()
  61. {
  62. var container = new ServiceContainer();
  63. Func<int, int, int> addOperation1 = (a, b) => a + b;
  64. container.AddService("Add", addOperation1);
  65. Func<int, int, int, int> addOperation2 = (a, b, c) => a + b + c;
  66. container.AddService("Add", addOperation2);
  67. Func<int, int, int, int, int> addOperation3 = (a, b, c, d) => a + b + c + d;
  68. container.AddService("Add", addOperation3);
  69. Assert.Equal(2, container.GetService<int>("Add", 1, 1));
  70. Assert.Equal(3, container.GetService<int>("Add", 1, 1, 1));
  71. Assert.Equal(4, container.GetService<int>("Add", 1, 1, 1, 1));
  72. }
  73. [Fact]
  74. public void ShouldConstructParametersFromContainer()
  75. {
  76. var targetConstructor = typeof(SampleClassWithMultipleConstructors).GetConstructor(new[]
  77. {
  78. typeof
  79. (
  80. ISampleService
  81. ),
  82. typeof
  83. (
  84. ISampleService
  85. )
  86. });
  87. // Initialize the container
  88. var mockSampleService = new Mock<ISampleService>();
  89. IServiceContainer container = new ServiceContainer();
  90. container.AddService(mockSampleService.Object);
  91. container.AddService<IArgumentResolver>(new ArgumentResolver());
  92. // Generate the arguments using the target constructor
  93. var arguments = targetConstructor.ResolveArgumentsFrom(container);
  94. Assert.Same(arguments[0], mockSampleService.Object);
  95. Assert.Same(arguments[1], mockSampleService.Object);
  96. }
  97. [Fact]
  98. public void ShouldConvertParameterInfoIntoPredicateThatChecksIfParameterTypeExistsAsService()
  99. {
  100. // Initialize the container so that it contains
  101. // an instance of ISampleService
  102. var mockSampleService = new Mock<ISampleService>();
  103. var container = new ServiceContainer();
  104. container.AddService(mockSampleService.Object);
  105. var constructor = typeof(SampleClassWithSingleArgumentConstructor)
  106. .GetConstructor(new[] {typeof(ISampleService)});
  107. var parameters = constructor.GetParameters();
  108. var firstParameter = parameters.First();
  109. Assert.NotNull(firstParameter);
  110. var mustExist = firstParameter.ParameterType.MustExistInContainer();
  111. Assert.True(mustExist(container));
  112. }
  113. [Fact]
  114. public void ShouldConvertTypeIntoPredicateThatChecksIfTypeExistsInContainerAsEnumerableSetOfServices()
  115. {
  116. var container = GetContainerWithMockSampleServices();
  117. var predicate = typeof(IEnumerable<ISampleService>)
  118. .ExistsAsEnumerableSetOfServices();
  119. Assert.True(predicate(container));
  120. }
  121. [Fact]
  122. public void ShouldConvertTypeIntoPredicateThatChecksIfTypeExistsInContainerAsServiceArray()
  123. {
  124. var container = GetContainerWithMockSampleServices();
  125. var predicate = typeof(ISampleService[])
  126. .ExistsAsServiceArray();
  127. Assert.True(predicate(container));
  128. }
  129. [Fact]
  130. public void ShouldCreateTypeWithAdditionalParameters()
  131. {
  132. var mockSampleService = new Mock<ISampleService>();
  133. IServiceContainer container = new ServiceContainer();
  134. // Add an ISampleService instance
  135. container.AddService(mockSampleService.Object);
  136. var resolver = container.GetService<IMemberResolver<ConstructorInfo>>();
  137. Assert.NotNull(resolver);
  138. var instance =
  139. container.AutoCreate(typeof(SampleClassWithAdditionalArgument), 42) as
  140. SampleClassWithAdditionalArgument;
  141. Assert.NotNull(instance);
  142. Assert.True(instance.Argument == 42);
  143. }
  144. [Fact]
  145. public void ShouldInjectConstructorWithNamedParameterTypes()
  146. {
  147. var mockDefaultSampleService = new Mock<ISampleService>();
  148. var mockOtherSampleService = new Mock<ISampleService>();
  149. var container = new ServiceContainer();
  150. // Add the default service
  151. container.AddService(mockDefaultSampleService.Object);
  152. // Add the expected service instance
  153. container.AddService("OtherService", mockOtherSampleService.Object);
  154. var serviceInstance =
  155. (SampleClassWithNamedParameters) container.AutoCreate(typeof(SampleClassWithNamedParameters));
  156. Assert.Equal(mockOtherSampleService.Object, serviceInstance.ServiceInstance);
  157. }
  158. [Fact]
  159. public void ShouldInstantiateClassWithNonServiceArguments()
  160. {
  161. var container = new ServiceContainer();
  162. container.AddDefaultServices();
  163. container.AddService(typeof(SampleClassWithNonServiceArgument), typeof(SampleClassWithNonServiceArgument));
  164. var text = "Hello, World!";
  165. string serviceName = null;
  166. var result = container.GetService<SampleClassWithNonServiceArgument>(serviceName, text);
  167. Assert.NotNull(result);
  168. Assert.True(result.Value == text);
  169. }
  170. [Fact]
  171. public void ShouldInstantiateClassWithServiceArrayAsConstructorArgument()
  172. {
  173. var container = GetContainerWithMockSampleServices();
  174. container.AddService(typeof(SampleClassWithServiceArrayAsConstructorArgument),
  175. typeof(SampleClassWithServiceArrayAsConstructorArgument));
  176. var result = container.GetService(typeof(SampleClassWithServiceArrayAsConstructorArgument)) as
  177. SampleClassWithServiceArrayAsConstructorArgument;
  178. Assert.NotNull(result);
  179. Assert.NotNull(result);
  180. Assert.NotNull(result.Services);
  181. Assert.True(result.Services.Count() > 0);
  182. }
  183. [Fact]
  184. public void ShouldInstantiateClassWithServiceEnumerableAsConstructorArgument()
  185. {
  186. var container = GetContainerWithMockSampleServices();
  187. container.AddService(typeof(SampleClassWithServiceEnumerableAsConstructorArgument),
  188. typeof(SampleClassWithServiceEnumerableAsConstructorArgument));
  189. var result =
  190. container.GetService(typeof(SampleClassWithServiceEnumerableAsConstructorArgument)) as
  191. SampleClassWithServiceEnumerableAsConstructorArgument;
  192. Assert.NotNull(result);
  193. Assert.NotNull(result);
  194. Assert.NotNull(result.Services);
  195. Assert.True(result.Services.Count() > 0);
  196. }
  197. [Fact]
  198. public void ShouldInstantiateObjectWithConstructorAndArguments()
  199. {
  200. var targetConstructor = typeof(SampleClassWithMultipleConstructors).GetConstructor(new[]
  201. {
  202. typeof
  203. (
  204. ISampleService
  205. ),
  206. typeof
  207. (
  208. ISampleService
  209. )
  210. });
  211. // Create the method arguments
  212. var mockSampleService = new Mock<ISampleService>();
  213. var arguments = new object[] {mockSampleService.Object, mockSampleService.Object};
  214. // Initialize the container
  215. IServiceContainer container = new ServiceContainer();
  216. container.AddDefaultServices();
  217. var constructorInvoke = container.GetService<IMethodInvoke<ConstructorInfo>>();
  218. var result = constructorInvoke.Invoke(null, targetConstructor, arguments);
  219. Assert.NotNull(result);
  220. Assert.Equal(typeof(SampleClassWithMultipleConstructors), result.GetType());
  221. }
  222. [Fact]
  223. public void ShouldReportThatServiceExistsForStronglyTypedFunctor()
  224. {
  225. var container = new ServiceContainer();
  226. Func<int, int, int> addOperation1 = (a, b) => a + b;
  227. container.AddService("Add", addOperation1);
  228. Assert.True(container.Contains("Add", typeof(int), 1, 1));
  229. }
  230. [Fact]
  231. public void ShouldResolveClassWithMultipleNonServiceArgumentConstructors()
  232. {
  233. IServiceContainer container = new ServiceContainer();
  234. container.AddDefaultServices();
  235. container.AddService("ClassWithMultipleNonServiceArgumentConstructors",
  236. typeof(ISampleService), typeof(SampleClassWithMultipleNonServiceArgumentConstructors),
  237. LifecycleType.OncePerRequest);
  238. // Match the correct constructor
  239. var sampleService = container.GetService<ISampleService>("ClassWithMultipleNonServiceArgumentConstructors",
  240. "test", 42, SampleEnum.One, (decimal) 3.14, 42);
  241. Assert.NotNull(sampleService);
  242. }
  243. [Fact]
  244. public void ShouldResolveConstructorWithAdditionalArgument()
  245. {
  246. var mockSampleService = new Mock<ISampleService>();
  247. IServiceContainer container = new ServiceContainer();
  248. // Add an ISampleService instance
  249. container.AddService(mockSampleService.Object);
  250. container.AddDefaultServices();
  251. var resolver = container.GetService<IMemberResolver<ConstructorInfo>>();
  252. Assert.NotNull(resolver);
  253. // The resolver should return the constructor
  254. // with the following signature: Constructor(ISampleService, int)
  255. var expectedConstructor =
  256. typeof(SampleClassWithAdditionalArgument).GetConstructor(new[] {typeof(ISampleService), typeof(int)});
  257. Assert.NotNull(expectedConstructor);
  258. var context = new MethodFinderContext(42);
  259. var result = resolver.ResolveFrom(typeof(SampleClassWithAdditionalArgument), container, context);
  260. Assert.Same(expectedConstructor, result);
  261. }
  262. [Fact]
  263. public void ShouldResolveConstructorWithMostResolvableParametersFromContainer()
  264. {
  265. var mockSampleService = new Mock<ISampleService>();
  266. IServiceContainer container = new ServiceContainer();
  267. // Add an ISampleService instance
  268. container.AddService(mockSampleService.Object);
  269. container.AddDefaultServices();
  270. var resolver = container.GetService<IMemberResolver<ConstructorInfo>>();
  271. Assert.NotNull(resolver);
  272. // The resolver should return the constructor with two ISampleService parameters
  273. var expectedConstructor =
  274. typeof(SampleClassWithMultipleConstructors).GetConstructor(new[]
  275. {
  276. typeof(ISampleService),
  277. typeof(ISampleService)
  278. });
  279. Assert.NotNull(expectedConstructor);
  280. var finderContext = new MethodFinderContext(new Type[0], new object[0], null);
  281. var result = resolver.ResolveFrom(typeof(SampleClassWithMultipleConstructors), container,
  282. finderContext);
  283. Assert.Same(expectedConstructor, result);
  284. }
  285. }
  286. }