diff --git a/CHANGELOG.md b/CHANGELOG.md index 97da8ffa7..386a13044 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1 #### Fixed * Wrong parameters count for extension methods in `Callback` and `Returns` (@Caraul, #575) +* `CallBase` regression with members of additional interfaces (@stakx, #583) ## 4.8.1 (2018-01-08) diff --git a/Moq.Tests/Regressions/IssueReportsFixture.cs b/Moq.Tests/Regressions/IssueReportsFixture.cs index b19e67aad..8cb97fe4c 100644 --- a/Moq.Tests/Regressions/IssueReportsFixture.cs +++ b/Moq.Tests/Regressions/IssueReportsFixture.cs @@ -1810,6 +1810,31 @@ public object DoSomething() #endregion + #region 582 + + public sealed class Issue582 + { + public interface IFoo + { + void Method(); + } + + public class Bar + { + } + + [Fact] + public void CallBase_has_no_effect_for_methods_of_additional_interfaces() + { + var bar = new Mock() { CallBase = true }; + var foo = bar.As().Object; + + foo.Method(); + } + } + + #endregion + // Old @ Google Code #region #47 diff --git a/Source/Interception/InterceptionAspects.cs b/Source/Interception/InterceptionAspects.cs index 2c4fcd903..ecafa6019 100644 --- a/Source/Interception/InterceptionAspects.cs +++ b/Source/Interception/InterceptionAspects.cs @@ -345,11 +345,23 @@ public override InterceptionAction Handle(Invocation invocation, Mock mock) Debug.Assert(mock.ImplementsInterface(declaringType)); // Case 2: Explicitly implemented interface method of a class proxy. - // Only call base method if it isn't an event accessor. - if (!method.LooksLikeEventAttach() && !method.LooksLikeEventDetach()) + + if (mock.InheritedInterfaces.Contains(declaringType)) { - invocation.ReturnBase(); - return InterceptionAction.Stop; + // Case 2a: Re-implemented interface. + // The base class has its own implementation. Only call base method if it isn't an event accessor. + if (!method.LooksLikeEventAttach() && !method.LooksLikeEventDetach()) + { + invocation.ReturnBase(); + return InterceptionAction.Stop; + } + } + else + { + Debug.Assert(mock.AdditionalInterfaces.Contains(declaringType)); + + // Case 2b: Additional interface. + // There is no base method to call, so fall through. } } }