diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a300eba9..d98bf676e 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 * `NullReferenceException` when using `SetupSet` on indexers with multiple parameters (@idigra, #694) +* `CallBase` should not be allowed for delegate mocks (@tehmantra, #706) ## 4.10.0 (2018-09-08) diff --git a/src/Moq/MethodCall.cs b/src/Moq/MethodCall.cs index 8203a2833..eb0a03e36 100644 --- a/src/Moq/MethodCall.cs +++ b/src/Moq/MethodCall.cs @@ -123,6 +123,11 @@ public override void Execute(Invocation invocation) public virtual void SetCallBaseResponse() { + if (this.Mock.TargetType.IsDelegate()) + { + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Resources.CallBaseCannotBeUsedWithDelegateMocks)); + } + this.callBase = true; } diff --git a/src/Moq/MethodCallReturn.cs b/src/Moq/MethodCallReturn.cs index e130c3b18..b30186029 100644 --- a/src/Moq/MethodCallReturn.cs +++ b/src/Moq/MethodCallReturn.cs @@ -58,6 +58,11 @@ public override void SetCallbackResponse(Delegate callback) public override void SetCallBaseResponse() { + if (this.Mock.TargetType.IsDelegate()) + { + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Resources.CallBaseCannotBeUsedWithDelegateMocks)); + } + this.returnValueKind = ReturnValueKind.CallBase; } diff --git a/src/Moq/Mock.Generic.cs b/src/Moq/Mock.Generic.cs index 9823ef6fd..2516aad91 100644 --- a/src/Moq/Mock.Generic.cs +++ b/src/Moq/Mock.Generic.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -18,6 +19,7 @@ using Moq.Language; using Moq.Language.Flow; +using Moq.Properties; namespace Moq { @@ -164,7 +166,15 @@ private void CheckParameters() public override bool CallBase { get => this.callBase; - set => this.callBase = value; + set + { + if (value && this.MockedType.IsDelegate()) + { + throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, Resources.CallBaseCannotBeUsedWithDelegateMocks)); + } + + this.callBase = value; + } } internal override Dictionary ConfiguredDefaultValues => this.configuredDefaultValues; diff --git a/src/Moq/Properties/Resources.Designer.cs b/src/Moq/Properties/Resources.Designer.cs index 23e17f0dc..099bcce05 100644 --- a/src/Moq/Properties/Resources.Designer.cs +++ b/src/Moq/Properties/Resources.Designer.cs @@ -87,6 +87,15 @@ internal static string AsMustBeInterface { } } + /// + /// Looks up a localized string similar to CallBase cannot be used with Delegate mocks.. + /// + internal static string CallBaseCannotBeUsedWithDelegateMocks { + get { + return ResourceManager.GetString("CallBaseCannotBeUsedWithDelegateMocks", resourceCulture); + } + } + /// /// Looks up a localized string similar to Can't set return value for void method {0}.. /// diff --git a/src/Moq/Properties/Resources.resx b/src/Moq/Properties/Resources.resx index e2a1e4bc9..6732fa30f 100644 --- a/src/Moq/Properties/Resources.resx +++ b/src/Moq/Properties/Resources.resx @@ -348,4 +348,7 @@ Expected invocation on the mock once, but was {4} times: {1} The following invocations on mock '{0}' were not verified: {1} - \ No newline at end of file + + CallBase cannot be used with Delegate mocks. + + diff --git a/tests/Moq.Tests/Regressions/IssueReportsFixture.cs b/tests/Moq.Tests/Regressions/IssueReportsFixture.cs index 32296da2b..e857fe99a 100644 --- a/tests/Moq.Tests/Regressions/IssueReportsFixture.cs +++ b/tests/Moq.Tests/Regressions/IssueReportsFixture.cs @@ -9,6 +9,7 @@ using System.Data.Entity.Core.EntityClient; #endif using System.ComponentModel; +using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; @@ -2010,6 +2011,51 @@ public interface IMyInterface #endregion + #region 706 + + public class Issue706 + { + [Fact] + public void CallBase_should_not_be_allowed_for_void_delegate_mocks() + { + Mock mock = new Mock(); + Language.Flow.ISetup setup = mock.Setup(m => m()); + + Exception ex = Assert.Throws(() => setup.CallBase()); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, Resources.CallBaseCannotBeUsedWithDelegateMocks), ex.Message); + } + + [Fact] + public void CallBase_should_not_be_allowed_for_non_void_delegate_mocks() + { + Mock> mock = new Mock>(); + Language.Flow.ISetup, bool> setup = mock.Setup(m => m()); + + Exception ex = Assert.Throws(() => setup.CallBase()); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, Resources.CallBaseCannotBeUsedWithDelegateMocks), ex.Message); + } + + [Fact] + public void CallBase_property_should_not_be_allowed_true_for_delegate_mocks() + { + Mock mock = new Mock(); + + Exception ex = Assert.Throws(() => mock.CallBase = true); + Assert.Equal(string.Format(CultureInfo.CurrentCulture, Resources.CallBaseCannotBeUsedWithDelegateMocks), ex.Message); + } + + [Fact] + public void CallBase_property_should_be_allowed_false_for_delegate_mocks() + { + Mock mock = new Mock(); + mock.CallBase = false; + + Assert.Equal(false, mock.CallBase); + } + } + + #endregion + // Old @ Google Code #region #47