From a1eaac6e00aab74683329dabf8ae3449c53e594d Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Fri, 13 Jan 2023 17:56:39 +0100 Subject: [PATCH 1/3] Add failing test for one `mock.Protected().Verify()` method overload --- .../Regressions/IssueReportsFixture.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/Moq.Tests/Regressions/IssueReportsFixture.cs b/tests/Moq.Tests/Regressions/IssueReportsFixture.cs index d8f285eaf..33aaf38ba 100644 --- a/tests/Moq.Tests/Regressions/IssueReportsFixture.cs +++ b/tests/Moq.Tests/Regressions/IssueReportsFixture.cs @@ -4024,6 +4024,34 @@ public interface IX } } +#endregion + +#region #1314 + + public class Issue1314 + { + [Fact] + public void Verify_protected_generic_non_void_method_using_exactParameterMatch_overload_uses_provided_generic_type_arguments() + { + var mock = new Mock(); + + _ = mock.Object.InvokeMethod(); + _ = mock.Object.InvokeMethod(); + _ = mock.Object.InvokeMethod(); + + mock.Protected().Verify("Method", new Type[] { typeof(float) }, Times.Never(), true); + mock.Protected().Verify("Method", new Type[] { typeof(bool) }, Times.Once(), true); + mock.Protected().Verify("Method", new Type[] { typeof(int) }, Times.Exactly(2), true); + } + + public abstract class C + { + protected abstract string Method(); + + public string InvokeMethod() => Method(); + } + } + #endregion // Old @ Google Code From caca113df2fe6bb0cbe8d73ca28e0b7fe6717fa0 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Fri, 13 Jan 2023 17:57:02 +0100 Subject: [PATCH 2/3] Don't throw away generic type arguments in impl --- src/Moq/Protected/ProtectedMock.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Moq/Protected/ProtectedMock.cs b/src/Moq/Protected/ProtectedMock.cs index ff1a12273..95eb65b2d 100644 --- a/src/Moq/Protected/ProtectedMock.cs +++ b/src/Moq/Protected/ProtectedMock.cs @@ -253,7 +253,7 @@ public void Verify(string methodName, Times times, bool exactParameterM public void Verify(string methodName, Type[] genericTypeArguments, Times times, bool exactParameterMatch, params object[] args) { Guard.NotNull(genericTypeArguments, nameof(genericTypeArguments)); - this.InternalVerify(methodName, null, times, exactParameterMatch, args); + this.InternalVerify(methodName, genericTypeArguments, times, exactParameterMatch, args); } private void InternalVerify(string methodName, Type[] genericTypeArguments, Times times, bool exactParameterMatch, params object[] args) From 4240ff468fa46e38f9a839919ddd3bd72ad5ccc2 Mon Sep 17 00:00:00 2001 From: Dominique Schuppli Date: Fri, 13 Jan 2023 17:58:29 +0100 Subject: [PATCH 3/3] Update the changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 251f30b30..151fcf2e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,11 @@ The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1 * `setup.Verifiable(Times times, [string failMessage])` method to specify the expected number of calls upfront. `mock.Verify[All]` can then be used to check whether the setup was called that many times. The upper bound (maximum allowed number of calls) will be checked right away, i.e. whenever a setup gets called. (@stakx, #1319) * Add `ThrowsAsync` methods for non-generic `ValueTask` (@johnthcall, #1235) +#### Fixed + +* Verifying a protected generic method that returns a value is broken (@nthornton2010, #1314) + + ## 4.18.4 (2022-12-30) #### Changed