// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System.Collections.Generic; using Moq; using Xunit; using Assert = Microsoft.TestCommon.AssertEx; namespace System.Web.Mvc.Test { public class DependencyResolverTest { [Fact] public void GuardClauses() { // Arrange var resolver = new DependencyResolver(); // Act & Assert Assert.ThrowsArgumentNull( () => resolver.InnerSetResolver((IDependencyResolver)null), "resolver" ); Assert.ThrowsArgumentNull( () => resolver.InnerSetResolver((object)null), "commonServiceLocator" ); Assert.ThrowsArgumentNull( () => resolver.InnerSetResolver(null, type => null), "getService" ); Assert.ThrowsArgumentNull( () => resolver.InnerSetResolver(type => null, null), "getServices" ); } [Fact] public void DefaultServiceLocatorBehaviorTests() { // Arrange var resolver = new DependencyResolver(); // Act & Assert Assert.NotNull(resolver.InnerCurrent.GetService()); // Concrete type Assert.Null(resolver.InnerCurrent.GetService()); // Abstract type Assert.Null(resolver.InnerCurrent.GetService()); // Interface Assert.Null(resolver.InnerCurrent.GetService(typeof(List<>))); // Open generic } [Fact] public void DefaultServiceLocatorResolvesNewInstances() { // Arrange var resolver = new DependencyResolver(); // Act object obj1 = resolver.InnerCurrent.GetService(); object obj2 = resolver.InnerCurrent.GetService(); // Assert Assert.NotSame(obj1, obj2); } public class MockableResolver { public virtual object Get(Type type) { throw new NotImplementedException(); } public virtual IEnumerable GetAll(Type type) { throw new NotImplementedException(); } } [Fact] public void ResolverPassesCallsToDelegateBasedResolver() { // Arrange var resolver = new DependencyResolver(); var mockResolver = new Mock(); resolver.InnerSetResolver(mockResolver.Object.Get, mockResolver.Object.GetAll); // Act & Assert resolver.InnerCurrent.GetService(typeof(object)); mockResolver.Verify(r => r.Get(typeof(object))); resolver.InnerCurrent.GetServices(typeof(string)); mockResolver.Verify(r => r.GetAll(typeof(string))); } public class MockableCommonServiceLocator { public virtual object GetInstance(Type type) { throw new NotImplementedException(); } public virtual IEnumerable GetAllInstances(Type type) { throw new NotImplementedException(); } } [Fact] public void ResolverPassesCallsToICommonServiceLocator() { // Arrange var resolver = new DependencyResolver(); var mockResolver = new Mock(); resolver.InnerSetResolver(mockResolver.Object); // Act & Assert resolver.InnerCurrent.GetService(typeof(object)); mockResolver.Verify(r => r.GetInstance(typeof(object))); resolver.InnerCurrent.GetServices(typeof(string)); mockResolver.Verify(r => r.GetAllInstances(typeof(string))); } class MissingGetInstance { public IEnumerable GetAllInstances(Type type) { return null; } } class MissingGetAllInstances { public object GetInstance(Type type) { return null; } } class GetInstanceHasWrongSignature { public string GetInstance(Type type) { return null; } public IEnumerable GetAllInstances(Type type) { return null; } } class GetAllInstancesHasWrongSignature { public object GetInstance(Type type) { return null; } public IEnumerable GetAllInstances(Type type) { return null; } } [Fact] public void ValidationOfCommonServiceLocatorTests() { // Arrange var resolver = new DependencyResolver(); // Act & Assert Assert.Throws( () => resolver.InnerSetResolver(new MissingGetInstance()), @"The type System.Web.Mvc.Test.DependencyResolverTest+MissingGetInstance does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator. Parameter name: commonServiceLocator" ); Assert.Throws( () => resolver.InnerSetResolver(new MissingGetAllInstances()), @"The type System.Web.Mvc.Test.DependencyResolverTest+MissingGetAllInstances does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator. Parameter name: commonServiceLocator" ); Assert.Throws( () => resolver.InnerSetResolver(new GetInstanceHasWrongSignature()), @"The type System.Web.Mvc.Test.DependencyResolverTest+GetInstanceHasWrongSignature does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator. Parameter name: commonServiceLocator" ); Assert.Throws( () => resolver.InnerSetResolver(new GetAllInstancesHasWrongSignature()), @"The type System.Web.Mvc.Test.DependencyResolverTest+GetAllInstancesHasWrongSignature does not appear to implement Microsoft.Practices.ServiceLocation.IServiceLocator. Parameter name: commonServiceLocator" ); } [Fact] public void DependencyResolverCache() { // Verify that when we ask for an interface twice, it only queries the underlying resolver once. var resolver = new DependencyResolver(); Mock resolverMock = new Mock(); resolverMock.Setup(r => r.GetService(typeof(object))).Returns(() => new object()); resolverMock.Setup(r => r.GetService(typeof(int))).Returns(15); resolver.InnerSetResolver(resolverMock.Object); object result1 = resolver.InnerCurrentCache.GetService(typeof(object)); // 1st call object otherResult = resolver.InnerCurrentCache.GetService(typeof(int)); // 2nd call object result2 = resolver.InnerCurrentCache.GetService(typeof(object)); // Cached result from 1st call resolverMock.Verify(r => r.GetService(typeof(object)), Times.Once()); resolverMock.Verify(r => r.GetService(typeof(int)), Times.Once()); Assert.Same(result1, result2); Assert.Equal(15, otherResult); } [Fact] public void ClearDependencyResolverCache() { // Verify that when we ask for an interface twice, it only queries the underlying resolver once. var resolver = new DependencyResolver(); Mock resolverMock = new Mock(); resolverMock.Setup(r => r.GetService(typeof(object))).Returns(() => new object()); resolverMock.Setup(r => r.GetService(typeof(int))).Returns(15); resolver.InnerSetResolver(resolverMock.Object); object result1 = resolver.InnerCurrentCache.GetService(typeof(object)); // 1st call object otherResult = resolver.InnerCurrentCache.GetService(typeof(int)); // 2nd call resolver.InnerSetResolver(resolverMock.Object); // This will clear the cache object result2 = resolver.InnerCurrentCache.GetService(typeof(object)); // 3rd call resolverMock.Verify(r => r.GetService(typeof(object)), Times.Exactly(2)); resolverMock.Verify(r => r.GetService(typeof(int)), Times.Once()); Assert.NotSame(result1, result2); Assert.Equal(15, otherResult); } } }