Skip to content

Commit fd5d8e1

Browse files
PatrickScottDSkzu
authored andcommitted
Return the list of verified invocations from all Verify methods so they can be used for sequence verification
1 parent 59a238b commit fd5d8e1

8 files changed

Lines changed: 222 additions & 131 deletions

File tree

src/Moq/IVerifyResult.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace Moq
8+
{
9+
/// <summary>
10+
/// A collection of invocations verified by a call to mock.Verify() or one of its variations
11+
/// </summary>
12+
/// <typeparam name="T">The type being mocked and verified</typeparam>
13+
public interface IVerifyResult<T> : IReadOnlyList<IInvocation> where T: class
14+
{
15+
/// <summary>
16+
/// The mock that was verified
17+
/// </summary>
18+
Mock<T> Mock { get; }
19+
}
20+
}

src/Moq/Mock.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ internal void Verify(Func<ISetup, bool> predicate, HashSet<Mock> verifiedMocks)
313313
}
314314
}
315315

316-
internal static void Verify(Mock mock, LambdaExpression expression, Times times, string failMessage)
316+
internal static IEnumerable<IInvocation> Verify(Mock mock, LambdaExpression expression, Times times, string failMessage)
317317
{
318318
Guard.NotNull(times, nameof(times));
319319

@@ -326,14 +326,15 @@ internal static void Verify(Mock mock, LambdaExpression expression, Times times,
326326
part.SetupEvaluatedSuccessfully(invocation);
327327
invocation.MarkAsVerified();
328328
}
329+
return invocationsToBeMarkedAsVerified.Select(pair => (IInvocation)pair.Item1);
329330
}
330331
else
331332
{
332333
throw MockException.NoMatchingCalls(mock, expression, failMessage, times, invocationCount);
333334
}
334335
}
335336

336-
internal static void VerifyGet(Mock mock, LambdaExpression expression, Times times, string failMessage)
337+
internal static IEnumerable<IInvocation> VerifyGet(Mock mock, LambdaExpression expression, Times times, string failMessage)
337338
{
338339
Guard.NotNull(expression, nameof(expression));
339340

@@ -343,31 +344,31 @@ internal static void VerifyGet(Mock mock, LambdaExpression expression, Times tim
343344
Guard.CanRead(property);
344345
}
345346

346-
Mock.Verify(mock, expression, times, failMessage);
347+
return Mock.Verify(mock, expression, times, failMessage);
347348
}
348349

349-
internal static void VerifySet(Mock mock, LambdaExpression expression, Times times, string failMessage)
350+
internal static IEnumerable<IInvocation> VerifySet(Mock mock, LambdaExpression expression, Times times, string failMessage)
350351
{
351352
Guard.NotNull(expression, nameof(expression));
352353
Guard.IsAssignmentToPropertyOrIndexer(expression, nameof(expression));
353354

354-
Mock.Verify(mock, expression, times, failMessage);
355+
return Mock.Verify(mock, expression, times, failMessage);
355356
}
356357

357-
internal static void VerifyAdd(Mock mock, LambdaExpression expression, Times times, string failMessage)
358+
internal static IEnumerable<IInvocation> VerifyAdd(Mock mock, LambdaExpression expression, Times times, string failMessage)
358359
{
359360
Guard.NotNull(expression, nameof(expression));
360361
Guard.IsEventAdd(expression, nameof(expression));
361362

362-
Mock.Verify(mock, expression, times, failMessage);
363+
return Mock.Verify(mock, expression, times, failMessage);
363364
}
364365

365-
internal static void VerifyRemove(Mock mock, LambdaExpression expression, Times times, string failMessage)
366+
internal static IEnumerable<IInvocation> VerifyRemove(Mock mock, LambdaExpression expression, Times times, string failMessage)
366367
{
367368
Guard.NotNull(expression, nameof(expression));
368369
Guard.IsEventRemove(expression, nameof(expression));
369370

370-
Mock.Verify(mock, expression, times, failMessage);
371+
return Mock.Verify(mock, expression, times, failMessage);
371372
}
372373

373374
internal static void VerifyNoOtherCalls(Mock mock)

src/Moq/Mock`1.cs

Lines changed: 110 additions & 74 deletions
Large diffs are not rendered by default.

src/Moq/Protected/IProtectedAsMock.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.ComponentModel;
67
using System.Linq.Expressions;
78

@@ -115,7 +116,8 @@ public interface IProtectedAsMock<T, TAnalog> : IFluentInterface
115116
/// </param>
116117
/// <param name="failMessage">Message to include in the thrown <see cref="MockException"/> if verification fails.</param>
117118
/// <exception cref="MockException">The specified invocation did not occur (or did not occur the specified number of times).</exception>
118-
void Verify(Expression<Action<TAnalog>> expression, Times? times = null, string failMessage = null);
119+
/// <returns>A list of matching invocations</returns>
120+
IVerifyResult<T> Verify(Expression<Action<TAnalog>> expression, Times? times = null, string failMessage = null);
119121

120122
/// <summary>
121123
/// Verifies that a specific invocation matching the given expression was performed on the mock.
@@ -129,7 +131,8 @@ public interface IProtectedAsMock<T, TAnalog> : IFluentInterface
129131
/// </param>
130132
/// <param name="failMessage">Message to include in the thrown <see cref="MockException"/> if verification fails.</param>
131133
/// <exception cref="MockException">The specified invocation did not occur (or did not occur the specified number of times).</exception>
132-
void Verify<TResult>(Expression<Func<TAnalog, TResult>> expression, Times? times = null, string failMessage = null);
134+
/// <returns>A list of matching invocations</returns>
135+
IVerifyResult<T> Verify<TResult>(Expression<Func<TAnalog, TResult>> expression, Times? times = null, string failMessage = null);
133136

134137
/// <summary>
135138
/// Verifies that a property was set on the mock.
@@ -143,7 +146,8 @@ public interface IProtectedAsMock<T, TAnalog> : IFluentInterface
143146
/// <exception cref="MockException">
144147
/// The invocation was not called the number of times specified by <paramref name="times"/>.
145148
/// </exception>
146-
void VerifySet(Action<TAnalog> setterExpression, Times? times = null, string failMessage = null);
149+
/// <returns>A list of matching invocations</returns>
150+
IVerifyResult<T> VerifySet(Action<TAnalog> setterExpression, Times? times = null, string failMessage = null);
147151

148152
/// <summary>
149153
/// Verifies that a property was read on the mock.
@@ -156,6 +160,7 @@ public interface IProtectedAsMock<T, TAnalog> : IFluentInterface
156160
/// </param>
157161
/// <param name="failMessage">Message to include in the thrown <see cref="MockException"/> if verification fails.</param>
158162
/// <exception cref="MockException">The specified invocation did not occur (or did not occur the specified number of times).</exception>
159-
void VerifyGet<TProperty>(Expression<Func<TAnalog, TProperty>> expression, Times? times = null, string failMessage = null);
163+
/// <returns>A list of matching invocations</returns>
164+
IVerifyResult<T> VerifyGet<TProperty>(Expression<Func<TAnalog, TProperty>> expression, Times? times = null, string failMessage = null);
160165
}
161166
}

src/Moq/Protected/IProtectedMock.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.ComponentModel;
67

78
using Moq.Language;
@@ -182,7 +183,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
182183
/// <param name="times">The number of times a method is allowed to be called.</param>
183184
/// <param name="args">The optional arguments for the invocation. If argument matchers are used,
184185
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
185-
void Verify(string methodName, Times times, params object[] args);
186+
/// <returns>A list of matching invocations</returns>
187+
IVerifyResult<TMock> Verify(string methodName, Times times, params object[] args);
186188

187189
/// <summary>
188190
/// Specifies a verify for a void method with the given <paramref name="methodName"/>,
@@ -196,7 +198,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
196198
/// <param name="times">The number of times a method is allowed to be called.</param>
197199
/// <param name="args">The optional arguments for the invocation. If argument matchers are used,
198200
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
199-
void Verify(string methodName, Type[] genericTypeArguments, Times times, params object[] args);
201+
/// <returns>A list of matching invocations</returns>
202+
IVerifyResult<TMock> Verify(string methodName, Type[] genericTypeArguments, Times times, params object[] args);
200203

201204
/// <summary>
202205
/// Specifies a verify for a void method with the given <paramref name="methodName"/>,
@@ -210,7 +213,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
210213
/// <param name="exactParameterMatch">Should the parameter types match exactly types that were provided</param>
211214
/// <param name="args">The optional arguments for the invocation. If argument matchers are used,
212215
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
213-
void Verify(string methodName, Times times, bool exactParameterMatch, params object[] args);
216+
/// <returns>A list of matching invocations</returns>
217+
IVerifyResult<TMock> Verify(string methodName, Times times, bool exactParameterMatch, params object[] args);
214218

215219
/// <summary>
216220
/// Specifies a verify for a void method with the given <paramref name="methodName"/>,
@@ -225,7 +229,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
225229
/// <param name="exactParameterMatch">Should the parameter types match exactly types that were provided</param>
226230
/// <param name="args">The optional arguments for the invocation. If argument matchers are used,
227231
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
228-
void Verify(string methodName, Type[] genericTypeArguments, Times times, bool exactParameterMatch, params object[] args);
232+
/// <returns>A list of matching invocations</returns>
233+
IVerifyResult<TMock> Verify(string methodName, Type[] genericTypeArguments, Times times, bool exactParameterMatch, params object[] args);
229234

230235
/// <summary>
231236
/// Specifies a verify for an invocation on a property or a non void method with the given
@@ -238,7 +243,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
238243
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
239244
/// <param name="times">The number of times a method is allowed to be called.</param>
240245
/// <typeparam name="TResult">The type of return value from the expression.</typeparam>
241-
void Verify<TResult>(string methodName, Times times, params object[] args);
246+
/// <returns>A list of matching invocations</returns>
247+
IVerifyResult<TMock> Verify<TResult>(string methodName, Times times, params object[] args);
242248

243249
/// <summary>
244250
/// Specifies a verify for an invocation on a property or a non void method with the given
@@ -252,7 +258,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
252258
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
253259
/// <param name="times">The number of times a method is allowed to be called.</param>
254260
/// <typeparam name="TResult">The type of return value from the expression.</typeparam>
255-
void Verify<TResult>(string methodName, Type[] genericTypeArguments, Times times, params object[] args);
261+
/// <returns>A list of matching invocations</returns>
262+
IVerifyResult<TMock> Verify<TResult>(string methodName, Type[] genericTypeArguments, Times times, params object[] args);
256263

257264
/// <summary>
258265
/// Specifies a verify for an invocation on a property or a non void method with the given
@@ -266,7 +273,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
266273
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
267274
/// <param name="times">The number of times a method is allowed to be called.</param>
268275
/// <typeparam name="TResult">The type of return value from the expression.</typeparam>
269-
void Verify<TResult>(string methodName, Times times, bool exactParameterMatch, params object[] args);
276+
/// <returns>A list of matching invocations</returns>
277+
IVerifyResult<TMock> Verify<TResult>(string methodName, Times times, bool exactParameterMatch, params object[] args);
270278

271279
/// <summary>
272280
/// Specifies a verify for an invocation on a property or a non void method with the given
@@ -281,7 +289,8 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
281289
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</param>
282290
/// <param name="times">The number of times a method is allowed to be called.</param>
283291
/// <typeparam name="TResult">The type of return value from the expression.</typeparam>
284-
void Verify<TResult>(string methodName, Type[] genericTypeArguments, Times times, bool exactParameterMatch, params object[] args);
292+
/// <returns>A list of matching invocations</returns>
293+
IVerifyResult<TMock> Verify<TResult>(string methodName, Type[] genericTypeArguments, Times times, bool exactParameterMatch, params object[] args);
285294

286295
/// <summary>
287296
/// Specifies a verify for an invocation on a property getter with the given
@@ -292,8 +301,9 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
292301
/// <param name="propertyName">The name of the property.</param>
293302
/// <param name="times">The number of times a method is allowed to be called.</param>
294303
/// <typeparam name="TProperty">The type of the property.</typeparam>
304+
/// <returns>A list of matching invocations</returns>
295305
// TODO should receive args to support indexers
296-
void VerifyGet<TProperty>(string propertyName, Times times);
306+
IVerifyResult<TMock> VerifyGet<TProperty>(string propertyName, Times times);
297307

298308
/// <summary>
299309
/// Specifies a setup for an invocation on a property setter with the given
@@ -306,8 +316,9 @@ IProtectedAsMock<TMock, TAnalog> As<TAnalog>()
306316
/// <param name="value">The property value.</param>
307317
/// <typeparam name="TProperty">The type of the property. If argument matchers are used,
308318
/// remember to use <see cref="ItExpr"/> rather than <see cref="It"/>.</typeparam>
319+
/// <returns>A list of matching invocations</returns>
309320
// TODO should receive args to support indexers
310-
void VerifySet<TProperty>(string propertyName, Times times, object value);
321+
IVerifyResult<TMock> VerifySet<TProperty>(string propertyName, Times times, object value);
311322

312323
#endregion
313324
}

src/Moq/Protected/ProtectedAsMock.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Diagnostics;
67
using System.Linq;
78
using System.Linq.Expressions;
@@ -153,7 +154,7 @@ public ISetupSequentialAction SetupSequence(Expression<Action<TAnalog>> expressi
153154
return new SetupSequencePhrase(setup);
154155
}
155156

156-
public void Verify(Expression<Action<TAnalog>> expression, Times? times = null, string failMessage = null)
157+
public IVerifyResult<T> Verify(Expression<Action<TAnalog>> expression, Times? times = null, string failMessage = null)
157158
{
158159
Guard.NotNull(expression, nameof(expression));
159160

@@ -167,10 +168,10 @@ public void Verify(Expression<Action<TAnalog>> expression, Times? times = null,
167168
throw new ArgumentException(ex.Message, nameof(expression));
168169
}
169170

170-
Mock.Verify(this.mock, rewrittenExpression, times ?? Times.AtLeastOnce(), failMessage);
171+
return new VerifyResult<T>(this.mock, Mock.Verify(this.mock, rewrittenExpression, times ?? Times.AtLeastOnce(), failMessage));
171172
}
172173

173-
public void Verify<TResult>(Expression<Func<TAnalog, TResult>> expression, Times? times = null, string failMessage = null)
174+
public IVerifyResult<T> Verify<TResult>(Expression<Func<TAnalog, TResult>> expression, Times? times = null, string failMessage = null)
174175
{
175176
Guard.NotNull(expression, nameof(expression));
176177

@@ -184,18 +185,18 @@ public void Verify<TResult>(Expression<Func<TAnalog, TResult>> expression, Times
184185
throw new ArgumentException(ex.Message, nameof(expression));
185186
}
186187

187-
Mock.Verify(this.mock, rewrittenExpression, times ?? Times.AtLeastOnce(), failMessage);
188+
return new VerifyResult<T>(this.mock, Mock.Verify(this.mock, rewrittenExpression, times ?? Times.AtLeastOnce(), failMessage));
188189
}
189190

190-
public void VerifySet(Action<TAnalog> setterExpression, Times? times = null, string failMessage = null)
191+
public IVerifyResult<T> VerifySet(Action<TAnalog> setterExpression, Times? times = null, string failMessage = null)
191192
{
192193
Guard.NotNull(setterExpression, nameof(setterExpression));
193194

194195
var rewrittenExpression = ReconstructAndReplaceSetter(setterExpression);
195-
Mock.VerifySet(mock, rewrittenExpression, times.HasValue ? times.Value : Times.AtLeastOnce(), failMessage);
196+
return new VerifyResult<T>(mock, Mock.VerifySet(mock, rewrittenExpression, times.HasValue ? times.Value : Times.AtLeastOnce(), failMessage));
196197
}
197198

198-
public void VerifyGet<TProperty>(Expression<Func<TAnalog, TProperty>> expression, Times? times = null, string failMessage = null)
199+
public IVerifyResult<T> VerifyGet<TProperty>(Expression<Func<TAnalog, TProperty>> expression, Times? times = null, string failMessage = null)
199200
{
200201
Guard.NotNull(expression, nameof(expression));
201202

@@ -209,7 +210,7 @@ public void VerifyGet<TProperty>(Expression<Func<TAnalog, TProperty>> expression
209210
throw new ArgumentException(ex.Message, nameof(expression));
210211
}
211212

212-
Mock.VerifyGet(this.mock, rewrittenExpression, times ?? Times.AtLeastOnce(), failMessage);
213+
return new VerifyResult<T>(this.mock, Mock.VerifyGet(this.mock, rewrittenExpression, times ?? Times.AtLeastOnce(), failMessage));
213214
}
214215

215216
LambdaExpression ReconstructAndReplaceSetter(Action<TAnalog> setterExpression)

0 commit comments

Comments
 (0)