forked from devlooped/moq
/
Mock`1.cs
1401 lines (1265 loc) · 55.6 KB
/
Mock`1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright (c) 2007, Clarius Consulting, Manas Technology Solutions, InSTEDD, and Contributors.
// All rights reserved. Licensed under the BSD 3-Clause License; see License.txt.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using Moq.Language;
using Moq.Language.Flow;
using Moq.Properties;
namespace Moq
{
/// <summary>
/// Provides a mock implementation of <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">Type to mock, which can be an interface, a class, or a delegate.</typeparam>
/// <remarks>
/// Any interface type can be used for mocking, but for classes, only abstract and virtual members can be mocked.
/// <para>
/// The behavior of the mock with regards to the setups and the actual calls is determined by the optional
/// <see cref = "MockBehavior" /> that can be passed to the<see cref="Mock{T}(MockBehavior)"/> constructor.
/// </para>
/// </remarks>
/// <example group="overview">
/// The following example shows establishing setups with specific values for method invocations:
/// <code>
/// // Arrange
/// var order = new Order(TALISKER, 50);
/// var warehouse = new Mock<IWarehouse>();
/// warehouse.Setup(w => w.HasInventory(TALISKER, 50)).Returns(true);
///
/// // Act
/// order.Fill(warehouse.Object);
///
/// // Assert
/// Assert.True(order.IsFilled);
/// </code>
/// </example>
/// <example group="overview">
/// The following example shows how to use the <see cref="It"/> class
/// to specify conditions for arguments instead of specific values:
/// <code>
/// // Arrange
/// var order = new Order(TALISKER, 50);
/// var warehouse = new Mock<IWarehouse>();
///
/// // shows how to expect a value within a range:
/// warehouse.Setup(x => x.HasInventory(
/// It.IsAny<string>(),
/// It.IsInRange(0, 100, Range.Inclusive)))
/// .Returns(false);
///
/// // shows how to throw for unexpected calls.
/// warehouse.Setup(x => x.Remove(
/// It.IsAny<string>(),
/// It.IsAny<int>()))
/// .Throws(new InvalidOperationException());
///
/// // Act
/// order.Fill(warehouse.Object);
///
/// // Assert
/// Assert.False(order.IsFilled);
/// </code>
/// </example>
public partial class Mock<T> : Mock, IMock<T> where T : class
{
private static Type[] inheritedInterfaces;
private static int serialNumberCounter;
static Mock()
{
inheritedInterfaces =
typeof(T)
.GetInterfaces()
.Where(i => ProxyFactory.Instance.IsTypeVisible(i) && !i.IsImport)
.ToArray();
serialNumberCounter = 0;
}
private T instance;
private List<Type> additionalInterfaces;
private Dictionary<Type, object> configuredDefaultValues;
private object[] constructorArguments;
private DefaultValueProvider defaultValueProvider;
private EventHandlerCollection eventHandlers;
private InvocationCollection invocations;
private string name;
private SetupCollection setups;
private MockBehavior behavior;
private bool callBase;
private Switches switches;
#region Ctors
/// <summary>
/// Ctor invoked by AsTInterface exclusively.
/// </summary>
internal Mock(bool skipInitialize)
{
// HACK: this is quick hackish.
// In order to avoid having an IMock<T> I relevant members
// virtual so that As<TInterface> overrides them (i.e. Interceptor).
// The skipInitialize parameter is not used at all, and it's
// just to differentiate this ctor that should do nothing
// from the regular ones which initializes the proxy, etc.
}
/// <summary>
/// Initializes an instance of the mock with <see cref="MockBehavior.Default"/> behavior.
/// </summary>
/// <example>
/// <code>
/// var mock = new Mock<IFormatProvider>();
/// </code>
/// </example>
public Mock()
: this(MockBehavior.Default)
{
}
/// <summary>
/// Initializes an instance of the mock with <see cref="MockBehavior.Default"/> behavior
/// and with the given constructor arguments for the class. (Only valid when <typeparamref name="T"/> is a class.)
/// </summary>
/// <param name="args">Optional constructor arguments if the mocked type is a class.</param>
/// <remarks>
/// The mock will try to find the best match constructor given the constructor arguments,
/// and invoke that to initialize the instance.This applies only for classes, not interfaces.
/// </remarks>
/// <example>
/// <code>
/// var mock = new Mock<MyProvider>(someArgument, 25);
/// </code>
/// </example>
public Mock(params object[] args)
: this(MockBehavior.Default, args)
{
}
/// <summary>
/// Initializes an instance of the mock with the specified <see cref="MockBehavior"/> behavior.
/// </summary>
/// <param name="behavior">Behavior of the mock.</param>
/// <example>
/// <code>
/// var mock = new Mock<IFormatProvider>(MockBehavior.Strict);
/// </code>
/// </example>
public Mock(MockBehavior behavior)
: this(behavior, new object[0])
{
}
/// <summary>
/// Initializes an instance of the mock with a specific <see cref="MockBehavior"/> behavior
/// and with the given constructor arguments for the class.
/// </summary>
/// <param name="behavior">Behavior of the mock.</param>
/// <param name="args">Optional constructor arguments if the mocked type is a class.</param>
/// <remarks>
/// The mock will try to find the best match constructor given the constructor arguments,
/// and invoke that to initialize the instance. This applies only to classes, not interfaces.
/// </remarks>
public Mock(MockBehavior behavior, params object[] args)
{
Guard.IsMockable(typeof(T));
if (args == null)
{
args = new object[] { null };
}
this.additionalInterfaces = new List<Type>();
this.behavior = behavior;
this.configuredDefaultValues = new Dictionary<Type, object>();
this.constructorArguments = args;
this.defaultValueProvider = DefaultValueProvider.Empty;
this.eventHandlers = new EventHandlerCollection();
this.invocations = new InvocationCollection(this);
this.name = CreateUniqueDefaultMockName();
this.setups = new SetupCollection();
this.switches = Switches.Default;
this.CheckParameters();
}
/// <summary>
/// Initializes an instance of the mock using the given constructor call including its
/// argument values and with a specific <see cref="MockBehavior"/> behavior.
/// </summary>
/// <param name="newExpression">Lambda expression that creates an instance of <typeparamref name="T"/>.</param>
/// <param name="behavior">Behavior of the mock.</param>
/// <example>
/// <code>var mock = new Mock<MyProvider>(() => new MyProvider(someArgument, 25), MockBehavior.Loose);</code>
/// </example>
public Mock(Expression<Func<T>> newExpression, MockBehavior behavior = MockBehavior.Default)
: this(behavior, Expressions.Visitors.ConstructorCallVisitor.ExtractArgumentValues(newExpression))
{
}
private static string CreateUniqueDefaultMockName()
{
var serialNumber = Interlocked.Increment(ref serialNumberCounter);
var name = new StringBuilder();
name.Append("Mock<").AppendNameOf(typeof(T)).Append(':').Append(serialNumber).Append('>');
return name.ToString();
}
private void CheckParameters()
{
if (this.constructorArguments.Length > 0)
{
if (typeof(T).IsInterface)
{
throw new ArgumentException(Resources.ConstructorArgsForInterface);
}
if (typeof(T).IsDelegateType())
{
throw new ArgumentException(Resources.ConstructorArgsForDelegate);
}
}
}
#endregion
#region Properties
/// <inheritdoc/>
public override MockBehavior Behavior => this.behavior;
/// <inheritdoc/>
public override bool CallBase
{
get => this.callBase;
set
{
if (value && this.MockedType.IsDelegateType())
{
throw new NotSupportedException(Resources.CallBaseCannotBeUsedWithDelegateMocks);
}
this.callBase = value;
}
}
internal override object[] ConstructorArguments => this.constructorArguments;
internal override Dictionary<Type, object> ConfiguredDefaultValues => this.configuredDefaultValues;
/// <summary>
/// Gets or sets the <see cref="DefaultValueProvider"/> instance that will be used
/// e. g. to produce default return values for unexpected invocations.
/// </summary>
public override DefaultValueProvider DefaultValueProvider
{
get => this.defaultValueProvider;
set => this.defaultValueProvider = value ?? throw new ArgumentNullException(nameof(value));
}
internal override DefaultValueProvider AutoSetupPropertiesDefaultValueProvider { get; set; }
internal override EventHandlerCollection EventHandlers => this.eventHandlers;
internal override List<Type> AdditionalInterfaces => this.additionalInterfaces;
internal override InvocationCollection MutableInvocations => this.invocations;
internal override bool IsObjectInitialized => this.instance != null;
/// <summary>
/// Exposes the mocked object instance.
/// </summary>
public virtual new T Object
{
get { return (T)base.Object; }
}
/// <summary>
/// Allows naming of your mocks, so they can be easily identified in error messages (e.g. from failed assertions).
/// </summary>
public string Name
{
get => this.name;
set => this.name = value;
}
/// <summary>
/// Returns the name of the mock.
/// </summary>
public override string ToString()
{
return this.Name;
}
private void InitializeInstance()
{
// Determine the set of interfaces that the proxy object should additionally implement.
var additionalInterfaceCount = this.AdditionalInterfaces.Count;
var interfaces = new Type[1 + additionalInterfaceCount];
interfaces[0] = typeof(IMocked<T>);
this.AdditionalInterfaces.CopyTo(0, interfaces, 1, additionalInterfaceCount);
this.instance = (T)ProxyFactory.Instance.CreateProxy(
typeof(T),
this,
interfaces,
this.constructorArguments);
}
/// <summary>
/// Returns the mocked object value.
/// </summary>
protected override object OnGetObject()
{
if (this.instance == null)
{
this.InitializeInstance();
}
return this.instance;
}
internal override Type MockedType => typeof(T);
internal override SetupCollection MutableSetups => this.setups;
internal override Type[] InheritedInterfaces => Mock<T>.inheritedInterfaces;
/// <summary>
/// A set of switches that influence how this mock will operate.
/// You can opt in or out of certain features via this property.
/// </summary>
public override Switches Switches
{
get => this.switches;
set => this.switches = value;
}
#endregion
/// <summary>
/// Adds an interface implementation to the mock, allowing setups to be specified for it.
/// </summary>
/// <remarks>
/// This method can only be called before the first use of the mock <see cref="Object"/> property,
/// at which point the runtime type has already been generated and no more interfaces can be added to it.
/// <para>
/// Also, <typeparamref name="TInterface"/> must be an interface and not a class,
/// which must be specified when creating the mock instead.
/// </para>
/// </remarks>
/// <typeparam name="TInterface">Type of interface to cast the mock to.</typeparam>
/// <exception cref="ArgumentException">The <typeparamref name="TInterface"/> specified is not an interface.</exception>
/// <exception cref="InvalidOperationException">
/// The mock type has already been generated by accessing the <see cref="Object"/> property.
/// </exception>
/// <example>
/// The following example creates a mock for the main interface
/// and later adds <see cref="IDisposable"/> to it to verify it's called by the consumer code:
/// <code>
/// var mock = new Mock<IProcessor>();
/// mock.Setup(x => x.Execute("ping"));
///
/// // add IDisposable interface
/// var disposable = mock.As<IDisposable>();
/// disposable.Setup(d => d.Dispose())
/// .Verifiable();
/// </code>
/// </example>
public override Mock<TInterface> As<TInterface>()
{
var interfaceType = typeof(TInterface);
if (!interfaceType.IsInterface)
{
throw new ArgumentException(Resources.AsMustBeInterface);
}
if (typeof(TInterface) == typeof(T))
{
return (Mock<TInterface>)(Mock)this;
}
if (this.IsObjectInitialized && this.ImplementsInterface(interfaceType) == false)
{
throw new InvalidOperationException(Resources.AlreadyInitialized);
}
if (this.AdditionalInterfaces.Contains(interfaceType) == false)
{
// We get here for either of two reasons:
//
// 1. We are being asked to implement an interface that the mocked type does *not* itself
// inherit or implement. We need to hand this interface type to DynamicProxy's
// `CreateClassProxy` method as an additional interface to be implemented.
//
// 2. The user is possibly going to create a setup through an interface type that the
// mocked type *does* implement. Since the mocked type might implement that interface's
// methods non-virtually, we can only intercept those if DynamicProxy reimplements the
// interface in the generated proxy type. Therefore we do the same as for (1).
this.AdditionalInterfaces.Add(interfaceType);
}
return new AsInterface<TInterface>(this);
}
#region Setup
/// <summary>
/// Specifies a setup on the mocked type for a call to a <see langword="void"/> method.
/// </summary>
/// <param name="expression">Lambda expression that specifies the expected method invocation.</param>
/// <remarks>
/// If more than one setup is specified for the same method or property,
/// the latest one wins and is the one that will be executed.
/// </remarks>
/// <example group="setups">
/// <code>
/// var mock = new Mock<IProcessor>();
/// mock.Setup(x => x.Execute("ping"));
/// </code>
/// </example>
public ISetup<T> Setup(Expression<Action<T>> expression)
{
var setup = Mock.Setup(this, expression, null);
return new VoidSetupPhrase<T>(setup);
}
/// <summary>
/// Specifies a setup on the mocked type for a call to a non-<see langword="void"/> (value-returning) method.
/// </summary>
/// <param name="expression">Lambda expression that specifies the method invocation.</param>
/// <typeparam name="TResult">Type of the return value. Typically omitted as it can be inferred from the expression.</typeparam>
/// <remarks>
/// If more than one setup is specified for the same method or property,
/// the latest one wins and is the one that will be executed.
/// </remarks>
/// <example group="setups">
/// <code>
/// mock.Setup(x => x.HasInventory("Talisker", 50))
/// .Returns(true);
/// </code>
/// </example>
public ISetup<T, TResult> Setup<TResult>(Expression<Func<T, TResult>> expression)
{
var setup = Mock.Setup(this, expression, null);
return new NonVoidSetupPhrase<T, TResult>(setup);
}
/// <summary>
/// Specifies a setup on the mocked type for a call to a property getter.
/// </summary>
/// <param name="expression">Lambda expression that specifies the property getter.</param>
/// <typeparam name="TProperty">Type of the property. Typically omitted as it can be inferred from the expression.</typeparam>
/// <remarks>
/// If more than one setup is set for the same property getter,
/// the latest one wins and is the one that will be executed.
/// </remarks>
/// <example group="setups">
/// <code>
/// mock.SetupGet(x => x.Suspended)
/// .Returns(true);
/// </code>
/// </example>
public ISetupGetter<T, TProperty> SetupGet<TProperty>(Expression<Func<T, TProperty>> expression)
{
var setup = Mock.SetupGet(this, expression, null);
return new NonVoidSetupPhrase<T, TProperty>(setup);
}
/// <summary>
/// Specifies a setup on the mocked type for a call to a property setter.
/// </summary>
/// <param name="setterExpression">The Lambda expression that sets a property to a value.</param>
/// <typeparam name="TProperty">Type of the property.</typeparam>
/// <remarks>
/// If more than one setup is set for the same property setter,
/// the latest one wins and is the one that will be executed.
/// <para>
/// This overloads allows the use of a callback already typed for the property type.
/// </para>
/// </remarks>
/// <example group="setups">
/// <code>
/// mock.SetupSet(x => x.Suspended = true);
/// </code>
/// </example>
public ISetupSetter<T, TProperty> SetupSet<TProperty>(Action<T> setterExpression)
{
Guard.NotNull(setterExpression, nameof(setterExpression));
var expression = ExpressionReconstructor.Instance.ReconstructExpression(setterExpression, this.ConstructorArguments);
var setup = Mock.SetupSet(this, expression, condition: null);
return new SetterSetupPhrase<T, TProperty>(setup);
}
/// <summary>
/// Specifies a setup on the mocked type for a call to a property setter.
/// </summary>
/// <param name="setterExpression">Lambda expression that sets a property to a value.</param>
/// <remarks>
/// If more than one setup is set for the same property setter,
/// the latest one wins and is the one that will be executed.
/// </remarks>
/// <example group="setups">
/// <code>
/// mock.SetupSet(x => x.Suspended = true);
/// </code>
/// </example>
public ISetup<T> SetupSet(Action<T> setterExpression)
{
Guard.NotNull(setterExpression, nameof(setterExpression));
var expression = ExpressionReconstructor.Instance.ReconstructExpression(setterExpression, this.ConstructorArguments);
var setup = Mock.SetupSet(this, expression, condition: null);
return new VoidSetupPhrase<T>(setup);
}
/// <summary>
/// Specifies a setup on the mocked type for a call to an event add.
/// </summary>
/// <param name="addExpression">Lambda expression that adds an event.</param>
/// <remarks>
/// If more than one setup is set for the same event add,
/// the latest one wins and is the one that will be executed.
/// </remarks>
/// <example group="setups">
/// <code>
/// mock.SetupAdd(x => x.EventHandler += (s, e) => {});
/// </code>
/// </example>
public ISetup<T> SetupAdd(Action<T> addExpression)
{
Guard.NotNull(addExpression, nameof(addExpression));
var expression = ExpressionReconstructor.Instance.ReconstructExpression(addExpression, this.ConstructorArguments);
var setup = Mock.SetupAdd(this, expression, condition: null);
return new VoidSetupPhrase<T>(setup);
}
/// <summary>
/// Specifies a setup on the mocked type for a call to an event remove.
/// </summary>
/// <param name="removeExpression">Lambda expression that removes an event.</param>
/// <remarks>
/// If more than one setup is set for the same event remove,
/// the latest one wins and is the one that will be executed.
/// </remarks>
/// <example group="setups">
/// <code>
/// mock.SetupRemove(x => x.EventHandler -= (s, e) => {});
/// </code>
/// </example>
public ISetup<T> SetupRemove(Action<T> removeExpression)
{
Guard.NotNull(removeExpression, nameof(removeExpression));
var expression = ExpressionReconstructor.Instance.ReconstructExpression(removeExpression, this.ConstructorArguments);
var setup = Mock.SetupRemove(this, expression, condition: null);
return new VoidSetupPhrase<T>(setup);
}
/// <summary>
/// Specifies that the given property should have "property behavior",
/// meaning that setting its value will cause it to be saved and later returned when the property is requested.
/// (This is also known as "stubbing".)
/// </summary>
/// <param name="property">Property expression to stub.</param>
/// <typeparam name="TProperty">
/// Type of the property, inferred from the property expression (does not need to be specified).
/// </typeparam>
/// <example group="setups">
/// If you have an interface with an int property <c>Value</c>,
/// you might stub it using the following straightforward call:
/// <code>
/// var mock = new Mock<IHaveValue>();
/// mock.SetupProperty(v => v.Value);
/// </code>
/// After the <c>SetupProperty</c> call has been issued, setting and retrieving
/// the object value will behave as expected:
/// <code>
/// IHaveValue v = mock.Object;
/// v.Value = 5;
/// Assert.Equal(5, v.Value);
/// </code>
/// </example>
public Mock<T> SetupProperty<TProperty>(Expression<Func<T, TProperty>> property)
{
return this.SetupProperty(property, default(TProperty));
}
/// <summary>
/// Specifies that the given property should have "property behavior",
/// meaning that setting its value will cause it to be saved and later returned when the property is requested.
/// This overload allows setting the initial value for the property.
/// (This is also known as "stubbing".)
/// </summary>
/// <param name="property">Property expression to stub.</param>
/// <param name="initialValue">Initial value for the property.</param>
/// <typeparam name="TProperty">
/// Type of the property, inferred from the property expression (does not need to be specified).
/// </typeparam>
/// <example group="setups">
/// If you have an interface with an int property <c>Value</c>,
/// you might stub it using the following straightforward call:
/// <code>
/// var mock = new Mock<IHaveValue>();
/// mock.SetupProperty(v => v.Value, 5);
/// </code>
/// After the <c>SetupProperty</c> call has been issued, setting and retrieving the object value
/// will behave as expected:
/// <code>
/// IHaveValue v = mock.Object;
/// Assert.Equal(5, v.Value); // Initial value was stored
///
/// // New value set which changes the initial value
/// v.Value = 6;
/// Assert.Equal(6, v.Value);
/// </code>
/// </example>
public Mock<T> SetupProperty<TProperty>(Expression<Func<T, TProperty>> property, TProperty initialValue)
{
Guard.NotNull(property, nameof(property));
var pi = property.ToPropertyInfo();
Guard.CanRead(pi);
Guard.CanWrite(pi);
TProperty value = initialValue;
this.SetupGet(property).Returns(() => value);
Mock.SetupSet(this, property.AssignItIsAny(), condition: null).SetCallbackBehavior(new Action<TProperty>(p => value = p));
return this;
}
/// <summary>
/// Specifies that the all properties on the mock should have "property behavior",
/// meaning that setting their value will cause them to be saved and later returned when the properties is requested.
/// (This is also known as "stubbing".)
/// The default value for each property will be the one generated as specified by the <see cref="Mock.DefaultValue"/>
/// property for the mock.
/// </summary>
/// <remarks>
/// If the mock's <see cref="Mock.DefaultValue"/> is set to <see cref="DefaultValue.Mock"/>,
/// the mocked default values will also get all properties setup recursively.
/// </remarks>
public Mock<T> SetupAllProperties()
{
SetupAllProperties(this);
return this;
}
/// <summary>
/// Return a sequence of values, once per call.
/// </summary>
public ISetupSequentialResult<TResult> SetupSequence<TResult>(Expression<Func<T, TResult>> expression)
{
var setup = Mock.SetupSequence(this, expression);
return new SetupSequencePhrase<TResult>(setup);
}
/// <summary>
/// Performs a sequence of actions, one per call.
/// </summary>
public ISetupSequentialAction SetupSequence(Expression<Action<T>> expression)
{
var setup = Mock.SetupSequence(this, expression);
return new SetupSequencePhrase(setup);
}
#endregion
#region When
/// <summary>
/// Allows setting up a conditional setup.
/// Conditional setups are only matched by an invocation
/// when the specified condition evaluates to <see langword="true"/>
/// at the time when the invocation occurs.
/// </summary>
/// <param name="condition">
/// The condition that should be checked
/// when a setup is being matched against an invocation.
/// </param>
public ISetupConditionResult<T> When(Func<bool> condition)
{
return new WhenPhrase<T>(this, new Condition(condition));
}
#endregion
#region Verify
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <exception cref="MockException">The invocation was not performed on the mock.</exception>
/// <example group="verification">
/// This example assumes that the mock has been used, and later we want to verify
/// that a given invocation with specific parameters was performed:
/// <code>
/// var mock = new Mock<IProcessor>();
///
/// ... // exercise mock
///
/// // Will throw if the test code didn't call Execute with a "ping" string argument.
/// mock.Verify(proc => proc.Execute("ping"));
/// </code>
/// </example>
public void Verify(Expression<Action<T>> expression)
{
Mock.Verify(this, expression, Times.AtLeastOnce(), null);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <exception cref="MockException">
/// The invocation was not called the number of times specified by <paramref name="times"/>.
/// </exception>
public void Verify(Expression<Action<T>> expression, Times times)
{
Mock.Verify(this, expression, times, null);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <exception cref="MockException">
/// The invocation was not called the number of times specified by <paramref name="times"/>.
/// </exception>
public void Verify(Expression<Action<T>> expression, Func<Times> times)
{
Verify(expression, times());
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock,
/// specifying a failure error message.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <exception cref="MockException">The invocation was not performed on the mock.</exception>
public void Verify(Expression<Action<T>> expression, string failMessage)
{
Mock.Verify(this, expression, Times.AtLeastOnce(), failMessage);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock,
/// specifying a failure error message.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <exception cref="MockException">
/// The invocation was not called the number of times specified by <paramref name="times"/>.
/// </exception>
public void Verify(Expression<Action<T>> expression, Times times, string failMessage)
{
Mock.Verify(this, expression, times, failMessage);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock,
/// specifying a failure error message.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <exception cref="MockException">
/// The invocation was not called the number of times specified by <paramref name="times"/>.
/// </exception>
public void Verify(Expression<Action<T>> expression, Func<Times> times, string failMessage)
{
Mock.Verify(this, expression, times(), failMessage);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <typeparam name="TResult">Type of return value from the expression.</typeparam>
/// <exception cref="MockException">The invocation was not performed on the mock.</exception>
/// <example group="verification">
/// This example assumes that the mock has been used, and later we want to verify
/// that a given invocation with specific parameters was performed:
/// <code>
/// var mock = new Mock<IWarehouse>();
///
/// ... // exercise mock
///
/// // Will throw if the test code didn't call HasInventory.
/// mock.Verify(warehouse => warehouse.HasInventory(TALISKER, 50));
/// </code>
/// </example>
public void Verify<TResult>(Expression<Func<T, TResult>> expression)
{
Mock.Verify(this, expression, Times.AtLeastOnce(), null);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <typeparam name="TResult">Type of return value from the expression.</typeparam>
/// <exception cref="MockException">
/// The invocation was not called the number of times specified by <paramref name="times"/>.
/// </exception>
public void Verify<TResult>(Expression<Func<T, TResult>> expression, Times times)
{
Mock.Verify(this, expression, times, null);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock.
/// Use in conjunction with the default <see cref="MockBehavior.Loose"/>.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <typeparam name="TResult">Type of return value from the expression.</typeparam>
/// <exception cref="MockException">
/// The invocation was not called the number of times specified by <paramref name="times"/>.
/// </exception>
public void Verify<TResult>(Expression<Func<T, TResult>> expression, Func<Times> times)
{
Mock.Verify(this, expression, times(), null);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock,
/// specifying a failure error message.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <typeparam name="TResult">Type of return value from the expression.</typeparam>
/// <exception cref="MockException">The invocation was not performed on the mock.</exception>
/// <example group="verification">
/// This example assumes that the mock has been used, and later we want to verify
/// that a given invocation with specific parameters was performed:
/// <code>
/// var mock = new Mock<IWarehouse>();
///
/// ... // exercise mock
///
/// // Will throw if the test code didn't call HasInventory.
/// mock.Verify(warehouse => warehouse.HasInventory(TALISKER, 50),
/// "When filling orders, inventory has to be checked");
/// </code>
/// </example>
public void Verify<TResult>(Expression<Func<T, TResult>> expression, string failMessage)
{
Mock.Verify(this, expression, Times.AtLeastOnce(), failMessage);
}
/// <summary>
/// Verifies that a specific invocation matching the given expression was performed on the mock,
/// specifying a failure error message.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <typeparam name="TResult">Type of return value from the expression.</typeparam>
/// <exception cref="MockException">
/// The invocation was not called the number times specified by <paramref name="times"/>.
/// </exception>
public void Verify<TResult>(Expression<Func<T, TResult>> expression, Times times, string failMessage)
{
Mock.Verify(this, expression, times, failMessage);
}
/// <summary>
/// Verifies that a property was read on the mock.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <typeparam name="TProperty">
/// Type of the property to verify. Typically omitted as it can be inferred from the expression's return type.
/// </typeparam>
/// <exception cref="MockException">The invocation was not performed on the mock.</exception>
/// <example group="verification">
/// This example assumes that the mock has been used, and later we want to verify
/// that a given property was retrieved from it:
/// <code>
/// var mock = new Mock<IWarehouse>();
///
/// ... // exercise mock
///
/// // Will throw if the test code didn't retrieve the IsClosed property.
/// mock.VerifyGet(warehouse => warehouse.IsClosed);
/// </code>
/// </example>
public void VerifyGet<TProperty>(Expression<Func<T, TProperty>> expression)
{
Mock.VerifyGet(this, expression, Times.AtLeastOnce(), null);
}
/// <summary>
/// Verifies that a property was read on the mock.
/// </summary>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <param name="expression">Expression to verify.</param>
/// <typeparam name="TProperty">
/// Type of the property to verify. Typically omitted as it can be inferred from the expression's return type.
/// </typeparam>
/// <exception cref="MockException">
/// The invocation was not called the number times specified by <paramref name="times"/>.
/// </exception>
public void VerifyGet<TProperty>(Expression<Func<T, TProperty>> expression, Times times)
{
Mock.VerifyGet(this, expression, times, null);
}
/// <summary>
/// Verifies that a property was read on the mock.
/// </summary>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <param name="expression">Expression to verify.</param>
/// <typeparam name="TProperty">
/// Type of the property to verify. Typically omitted as it can be inferred from the expression's return type.
/// </typeparam>
/// <exception cref="MockException">
/// The invocation was not called the number times specified by <paramref name="times"/>.
/// </exception>
public void VerifyGet<TProperty>(Expression<Func<T, TProperty>> expression, Func<Times> times)
{
VerifyGet(this, expression, times(), null);
}
/// <summary>
/// Verifies that a property was read on the mock, specifying a failure error message.
/// </summary>
/// <param name="expression">Expression to verify.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <typeparam name="TProperty">
/// Type of the property to verify. Typically omitted as it can be inferred from the expression's return type.
/// </typeparam>
/// <exception cref="MockException">The invocation was not performed on the mock.</exception>
public void VerifyGet<TProperty>(Expression<Func<T, TProperty>> expression, string failMessage)
{
Mock.VerifyGet(this, expression, Times.AtLeastOnce(), failMessage);
}
/// <summary>
/// Verifies that a property was read on the mock, specifying a failure error message.
/// </summary>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <param name="expression">Expression to verify.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <typeparam name="TProperty">
/// Type of the property to verify. Typically omitted as it can be inferred from the expression's return type.
/// </typeparam>
/// <exception cref="MockException">
/// The invocation was not called the number times specified by <paramref name="times"/>.
/// </exception>
public void VerifyGet<TProperty>(Expression<Func<T, TProperty>> expression, Times times, string failMessage)
{
Mock.VerifyGet(this, expression, times, failMessage);
}
/// <summary>
/// Verifies that a property was read on the mock, specifying a failure error message.
/// </summary>
/// <param name="times">The number of times a method is expected to be called.</param>
/// <param name="expression">Expression to verify.</param>
/// <param name="failMessage">Message to show if verification fails.</param>
/// <typeparam name="TProperty">
/// Type of the property to verify. Typically omitted as it can be inferred from the expression's return type.
/// </typeparam>
/// <exception cref="MockException">
/// The invocation was not called the number times specified by <paramref name="times"/>.
/// </exception>
public void VerifyGet<TProperty>(Expression<Func<T, TProperty>> expression, Func<Times> times, string failMessage)
{
VerifyGet(this, expression, times(), failMessage);
}
/// <summary>