diff --git a/Source/InterceptorStrategies.cs b/Source/InterceptorStrategies.cs index 3fb9dacfe..d58b0ad0a 100644 --- a/Source/InterceptorStrategies.cs +++ b/Source/InterceptorStrategies.cs @@ -33,8 +33,9 @@ internal class InvokeBase : IInterceptStrategy { public InterceptionAction HandleIntercept(ICallContext invocation, InterceptorContext ctx, CurrentInterceptContext localctx) { - if (invocation.Method.DeclaringType == typeof(object) || - invocation.Method.DeclaringType.IsClass && !invocation.Method.IsAbstract && ctx.Mock.CallBase + if (invocation.Method.DeclaringType == typeof(object) || // interface proxy + ctx.Mock.ImplementedInterfaces.Contains(invocation.Method.DeclaringType) && !invocation.Method.IsEventAttach() && !invocation.Method.IsEventDetach() && ctx.Mock.CallBase || // class proxy with explicitly implemented interfaces. The method's declaring type is the interface and the method couldn't be abstract + invocation.Method.DeclaringType.IsClass && !invocation.Method.IsAbstract && ctx.Mock.CallBase // class proxy ) { // Invoke underlying implementation. diff --git a/Source/Mock.Generic.cs b/Source/Mock.Generic.cs index d60cdc5d5..9ec5c4734 100644 --- a/Source/Mock.Generic.cs +++ b/Source/Mock.Generic.cs @@ -40,6 +40,7 @@ using System; using System.Diagnostics.CodeAnalysis; +using System.Linq; using System.Linq.Expressions; using Moq.Language.Flow; using Moq.Proxy; @@ -111,7 +112,7 @@ public Mock(MockBehavior behavior, params object[] args) this.Behavior = behavior; this.Interceptor = new Interceptor(behavior, typeof(T), this); this.constructorArguments = args; - this.ImplementedInterfaces.AddRange(typeof(T).GetInterfaces()); + this.ImplementedInterfaces.AddRange(typeof(T).GetInterfaces().Where(i => (i.IsPublic || i.IsNestedPublic) && !i.IsImport)); this.ImplementedInterfaces.Add(typeof(IMocked)); this.CheckParameters(); diff --git a/UnitTests/AsInterfaceFixture.cs b/UnitTests/AsInterfaceFixture.cs index d71fdf4bf..13e6a0596 100644 --- a/UnitTests/AsInterfaceFixture.cs +++ b/UnitTests/AsInterfaceFixture.cs @@ -152,6 +152,23 @@ public void VerifiesExpectationOnAddedInterfaceCastedDynamically() bag.As().Verify(f => f.Execute()); } + [Fact] + public void ShouldBeAbleToCastToImplementedInterface() + { + var fooBar = new Mock(); + var obj = fooBar.Object; + Assert.DoesNotThrow(() => fooBar.As()); + } + + [Fact] + public void ShouldNotThrowIfCallExplicitlyImplementedInterfacesMethodWhenCallBaseIsTrue() + { + var fooBar = new Mock(); + fooBar.CallBase = true; + var bag = (IBag)fooBar.Object; + Assert.DoesNotThrow(() => bag.Get("test")); + } + public interface IFoo { void Execute(); @@ -168,5 +185,36 @@ public interface IBag void Add(string key, object o); object Get(string key); } + + internal interface IBar + { + void Test(); + } + + public abstract class FooBar : IFoo, IBag, IBar + { + public abstract void Execute(); + + public abstract string Execute(string command); + + public abstract string Execute(string arg1, string arg2); + + public abstract string Execute(string arg1, string arg2, string arg3); + + public abstract string Execute(string arg1, string arg2, string arg3, string arg4); + + public abstract int Value { get; set; } + + void IBag.Add(string key, object o) + { + } + + object IBag.Get(string key) + { + return null; + } + + public abstract void Test(); + } } }