diff --git a/src/Mimic/Arg.cs b/src/Mimic/Arg.cs
index 1f65943..e34cd56 100644
--- a/src/Mimic/Arg.cs
+++ b/src/Mimic/Arg.cs
@@ -4,17 +4,40 @@
namespace Mimic;
+///
+/// Provides argument matchers for use in mock setups and verifications.
+///
[PublicAPI]
public static class Arg
{
+ ///
+ /// Matches any value of type , including null.
+ ///
+ /// The type of the argument to match.
+ /// An argument matcher that matches any value of the specified type.
public static TValue Any() => typeof(TValue).IsOrContainsGenericMatcher()
? ArgumentMatcher.Create((argument, parameterType) => argument == null || parameterType.IsInstanceOfType(argument))!
: ArgumentMatcher.Create(argument => argument == null || argument is TValue)!;
+ ///
+ /// Matches any non-null value of type .
+ ///
+ /// The type of the argument to match.
+ /// An argument matcher that matches any non-null value of the specified type.
public static TValue AnyNotNull() => typeof(TValue).IsOrContainsGenericMatcher()
? ArgumentMatcher.Create((argument, parameterType) => argument != null && parameterType.IsInstanceOfType(argument))!
: ArgumentMatcher.Create(argument => argument is TValue)!;
+ ///
+ /// Matches an argument that is equal to the specified value using the default equality comparer.
+ ///
+ /// The type of the argument to match.
+ /// The value to match against.
+ /// An argument matcher that matches the specified value.
+ ///
+ /// This overload does not support generic matchers due to the strongly typed value.
+ /// For generic matchers, use the overload with Expression<Func<object, Type, bool>> match instead.
+ ///
public static TValue Is(TValue value)
{
Guard.Assert(!typeof(TValue).IsOrContainsGenericMatcher(), "This overload does not support generic matchers due to the strongly typed value. Please use the overload with `Expression> predicate` instead.");
@@ -22,6 +45,17 @@ public static TValue Is(TValue value)
return ArgumentMatcher.Create(argument => Equals(argument, value))!;
}
+ ///
+ /// Matches an argument that is equal to the specified value using the provided equality comparer.
+ ///
+ /// The type of the argument to match.
+ /// The value to match against.
+ /// The equality comparer to use for comparison.
+ /// An argument matcher that matches the specified value using the provided comparer.
+ ///
+ /// This overload does not support generic matchers due to the strongly typed value.
+ /// For generic matchers, use the overload with Expression<Func<object, Type, bool>> match instead.
+ ///
public static TValue Is(TValue value, IEqualityComparer comparer)
{
Guard.Assert(!typeof(TValue).IsOrContainsGenericMatcher(), "This overload does not support generic matchers due to the strongly typed value. Please use the overload with `Expression> predicate` instead.");
@@ -29,6 +63,16 @@ public static TValue Is(TValue value, IEqualityComparer comparer
return ArgumentMatcher.Create(argument => comparer.Equals(argument, value))!;
}
+ ///
+ /// Matches an argument that satisfies the specified predicate expression.
+ ///
+ /// The type of the argument to match.
+ /// The predicate expression that the argument must satisfy.
+ /// An argument matcher that matches arguments satisfying the predicate.
+ ///
+ /// This overload does not support generic matchers due to the strongly typed value.
+ /// For generic matchers, use the overload with Expression<Func<object, Type, bool>> match instead.
+ ///
public static TValue Is(Expression> match)
{
Guard.Assert(!typeof(TValue).IsOrContainsGenericMatcher(), "This overload does not support generic matchers due to the strongly typed value. Please use the overload with `Expression> predicate` instead.");
@@ -36,29 +80,81 @@ public static TValue Is(Expression> match)
return ArgumentMatcher.Create(argument => match.Compile().Invoke(argument!))!;
}
+ ///
+ /// Matches an argument that satisfies the specified predicate expression with type information.
+ /// This overload supports generic matchers.
+ ///
+ /// The type of the argument to match.
+ /// The predicate expression that takes the argument and its parameter type.
+ /// An argument matcher that matches arguments satisfying the predicate.
public static TValue Is(Expression> match) =>
ArgumentMatcher.Create((argument, parameterType) => match.Compile().Invoke(argument!, parameterType))!;
+ ///
+ /// Matches an argument contained in the specified collection of values.
+ ///
+ /// The type of the argument to match.
+ /// The collection of values to check against.
+ /// An argument matcher that matches values contained in the collection.
public static TValue In(IEnumerable values) =>
ArgumentMatcher.Create(argument => values.Contains(argument))!;
+ ///
+ /// Matches an argument contained in the specified collection of values using the provided equality comparer.
+ ///
+ /// The type of the argument to match.
+ /// The collection of values to check against.
+ /// The equality comparer to use for comparison.
+ /// An argument matcher that matches values contained in the collection using the comparer.
public static TValue In(IEnumerable values, IEqualityComparer comparer) =>
ArgumentMatcher.Create(argument => values.Contains(argument, comparer!))!;
+ ///
+ /// Matches an argument contained in the specified array of values.
+ ///
+ /// The type of the argument to match.
+ /// The array of values to check against.
+ /// An argument matcher that matches values contained in the array.
public static TValue In(params TValue[] values) =>
ArgumentMatcher.Create(argument => values.Contains(argument))!;
+ ///
+ /// Matches an argument not contained in the specified collection of values.
+ ///
+ /// The type of the argument to match.
+ /// The collection of values to check against.
+ /// An argument matcher that matches values not contained in the collection.
public static TValue NotIn(IEnumerable values) =>
ArgumentMatcher.Create(argument => !values.Contains(argument))!;
+ ///
+ /// Matches an argument not contained in the specified collection of values using the provided equality comparer.
+ ///
+ /// The type of the argument to match.
+ /// The collection of values to check against.
+ /// The equality comparer to use for comparison.
+ /// An argument matcher that matches values not contained in the collection using the comparer.
public static TValue NotIn(IEnumerable values, IEqualityComparer comparer) =>
ArgumentMatcher.Create(argument => !values.Contains(argument, comparer!))!;
+ ///
+ /// Matches an argument not contained in the specified array of values.
+ ///
+ /// The type of the argument to match.
+ /// The array of values to check against.
+ /// An argument matcher that matches values not contained in the array.
public static TValue NotIn(params TValue[] values) =>
ArgumentMatcher.Create(argument => !values.Contains(argument))!;
+ ///
+ /// Provides reference argument matchers for ref parameters.
+ ///
+ /// The type of the reference argument.
public static class Ref
{
+ ///
+ /// Matches any reference argument of type .
+ ///
#pragma warning disable CA2211
public static TValue Any = default!;
#pragma warning restore CA2211
diff --git a/src/Mimic/CallCount.cs b/src/Mimic/CallCount.cs
index ad57240..2a25820 100644
--- a/src/Mimic/CallCount.cs
+++ b/src/Mimic/CallCount.cs
@@ -1,5 +1,8 @@
namespace Mimic;
+///
+/// Represents a call count constraint that can be used to verify the number of times a method was invoked.
+///
[PublicAPI]
public readonly struct CallCount : IEquatable
{
@@ -14,28 +17,62 @@ private CallCount(Type type, int from, int to)
_to = to;
}
+ ///
+ /// Creates a call count constraint that requires at least one invocation.
+ ///
+ /// A that validates if a method was called at least once.
public static CallCount AtLeastOnce() => new(Type.AtLeastOnce, 1, int.MaxValue);
+ ///
+ /// Creates a call count constraint that requires at least the specified number of invocations.
+ ///
+ /// The minimum number of invocations required.
+ /// A that validates if a method was called at least the specified number of times.
+ /// Thrown when is less than 1.
public static CallCount AtLeast(int count)
{
Guard.Assert(count >= 1);
return new CallCount(Type.AtLeast, count, int.MaxValue);
}
+ ///
+ /// Creates a call count constraint that allows at most the specified number of invocations.
+ ///
+ /// The maximum number of invocations allowed.
+ /// A that validates if a method was called at most the specified number of times.
+ /// Thrown when is less than 1.
public static CallCount AtMost(int count)
{
Guard.Assert(count >= 1);
return new CallCount(Type.AtMost, 0, count);
}
+ ///
+ /// Creates a call count constraint that allows at most one invocation.
+ ///
+ /// A that validates if a method was called at most once.
public static CallCount AtMostOnce() => new(Type.AtMostOnce, 0, 1);
+ ///
+ /// Creates a call count constraint that requires the number of invocations to be within the specified range (inclusive).
+ ///
+ /// The minimum number of invocations (inclusive).
+ /// The maximum number of invocations (inclusive).
+ /// A that validates if a method was called within the specified range.
+ /// Thrown when is negative or is less than .
public static CallCount InclusiveBetween(int from, int to)
{
Guard.Assert(from >= 0 && to >= from);
return new CallCount(Type.InclusiveBetween, from, to);
}
+ ///
+ /// Creates a call count constraint that requires the number of invocations to be within the specified range (exclusive).
+ ///
+ /// The minimum number of invocations (exclusive).
+ /// The maximum number of invocations (exclusive).
+ /// A that validates if a method was called within the specified range.
+ /// Thrown when is not positive, is not greater than , or the difference between and is 1.
public static CallCount ExclusiveBetween(int from, int to)
{
Guard.Assert(from > 0 && to > from);
@@ -44,16 +81,35 @@ public static CallCount ExclusiveBetween(int from, int to)
return new CallCount(Type.ExclusiveBetween, from + 1, to - 1);
}
+ ///
+ /// Creates a call count constraint that requires exactly the specified number of invocations.
+ ///
+ /// The exact number of invocations required.
+ /// A that validates if a method was called exactly the specified number of times.
+ /// Thrown when is not positive.
public static CallCount Exactly(int count)
{
Guard.Assert(count > 0);
return new CallCount(Type.Exactly, count, count);
}
+ ///
+ /// Creates a call count constraint that requires exactly one invocation.
+ ///
+ /// A that validates if a method was called exactly once.
public static CallCount Once() => new(Type.Once, 1, 1);
+ ///
+ /// Creates a call count constraint that requires zero invocations.
+ ///
+ /// A that validates if a method was never called.
public static CallCount Never() => new(Type.Never, 0, 0);
+ ///
+ /// Validates whether the specified call count satisfies this constraint.
+ ///
+ /// The actual number of invocations to validate.
+ /// true if the call count satisfies this constraint; otherwise, false.
public bool Validate(int count) => _from <= count && count <= _to;
public bool Equals(CallCount other) => _from == other._from && _to == other._to;
diff --git a/src/Mimic/Generic.cs b/src/Mimic/Generic.cs
index 024d2df..d0438e0 100644
--- a/src/Mimic/Generic.cs
+++ b/src/Mimic/Generic.cs
@@ -1,25 +1,111 @@
namespace Mimic;
+///
+/// Provides generic type matchers for use with mock setups and argument matching.
+/// These matchers work in conjunction with the class to enable
+/// flexible type matching in generic method scenarios.
+///
[PublicAPI]
public sealed class Generic
{
+ ///
+ /// A generic type matcher that matches any type without restrictions.
+ /// This matcher accepts all types, including value types, reference types,
+ /// interfaces, and abstract classes.
+ ///
+ ///
+ /// Use this matcher when you want to accept any generic type argument in your mock setup.
+ /// This is equivalent to an unconstrained generic type parameter.
+ ///
+ ///
+ ///
+ /// // Matches any generic method call regardless of the type argument
+ /// mimic.Setup(m => m.GenericMethod<Generic.AnyType>()).Returns(true);
+ ///
+ ///
public sealed class AnyType : IGenericMatcher
{
+ ///
+ /// Determines whether the specified generic type matches this matcher.
+ ///
+ /// The generic type to evaluate.
+ /// Always returns true since this matcher accepts any type.
public bool Matches(Type genericType) => true;
}
+ ///
+ /// A generic type matcher that matches only reference types.
+ /// This includes classes, interfaces, delegates, and arrays, but excludes value types like structs and enums.
+ ///
+ ///
+ /// Use this matcher when you want to restrict generic type arguments to reference types only.
+ /// This is equivalent to a generic type parameter with a class constraint.
+ ///
+ ///
+ ///
+ /// // Matches generic method calls only when the type argument is a reference type
+ /// mimic.Setup(m => m.GenericMethod<Generic.AnyReferenceType>()).Returns("reference type");
+ ///
+ ///
public sealed class AnyReferenceType : IGenericMatcher
{
+ ///
+ /// Determines whether the specified generic type matches this matcher.
+ ///
+ /// The generic type to evaluate.
+ /// true if the type is a reference type; otherwise, false.
public bool Matches(Type genericType) => !genericType.IsValueType;
}
+ ///
+ /// A generic type matcher that matches types that are assignable from a specified type .
+ /// This includes the type itself and any types that inherit from or implement .
+ ///
+ /// The base type or interface that the generic type argument must be assignable from.
+ ///
+ /// Use this matcher when you want to restrict generic type arguments to types that have a specific inheritance relationship.
+ /// This is useful for matching generic methods that should only work with certain type hierarchies.
+ ///
+ ///
+ ///
+ /// // Matches generic method calls only when the type argument implements IDisposable
+ /// mimic.Setup(m => m.GenericMethod<Generic.AssignableFromType<IDisposable>>()).Returns(true);
+ ///
+ /// // Matches generic method calls only when the type argument inherits from Exception
+ /// mimic.Setup(m => m.HandleException<Generic.AssignableFromType<Exception>>()).Returns("handled");
+ ///
+ ///
public sealed class AssignableFromType : IGenericMatcher
{
+ ///
+ /// Determines whether the specified generic type matches this matcher.
+ ///
+ /// The generic type to evaluate.
+ /// true if is assignable from the generic type; otherwise, false.
public bool Matches(Type genericType) => typeof(T).IsAssignableFrom(genericType);
}
+ ///
+ /// A generic type matcher that matches only value types.
+ /// This includes structs, enums, and primitive types, but excludes reference types like classes and interfaces.
+ ///
+ ///
+ /// Use this matcher when you want to restrict generic type arguments to value types only.
+ /// This is equivalent to a generic type parameter with a struct constraint.
+ ///
+ ///
+ ///
+ /// // Matches generic method calls only when the type argument is a value type
+ /// mimic.Setup(m => m.GenericMethod<Generic.AnyValueType>()).Returns(42);
+ ///
+ ///
public readonly struct AnyValueType : IGenericMatcher
{
+ ///
+ /// Determines whether the specified generic type matches this matcher.
+ ///
+ /// The generic type to evaluate.
+ /// true if the type is a value type; otherwise, false.
public bool Matches(Type genericType) => genericType.IsValueType;
}
}
diff --git a/src/Mimic/IGenericMatcher.cs b/src/Mimic/IGenericMatcher.cs
index c422171..53effb2 100644
--- a/src/Mimic/IGenericMatcher.cs
+++ b/src/Mimic/IGenericMatcher.cs
@@ -1,7 +1,82 @@
namespace Mimic;
+///
+/// Defines a contract for matching generic types in mock setups and argument matching scenarios.
+/// Implementing types can create custom generic type matchers that work with the Mimic framework
+/// to provide flexible type matching for generic method calls.
+///
+///
+///
+/// This interface is used by the Mimic framework to determine whether a generic type argument
+/// matches specific criteria during mock setup and verification. Implementations of this interface
+/// can be used as type arguments in generic method setups to create flexible matching rules.
+///
+///
+/// The built-in class provides several common implementations of this interface,
+/// including matchers for any type, reference types, value types, and types assignable from a base type.
+/// Custom implementations can extend this functionality for specific matching requirements.
+///
+///
+///
+/// Creating a custom matcher:
+///
+/// public class NumericTypeMatcher : IGenericMatcher
+/// {
+/// public bool Matches(Type genericType)
+/// {
+/// return genericType == typeof(int) || genericType == typeof(double) ||
+/// genericType == typeof(decimal) || genericType == typeof(float);
+/// }
+/// }
+///
+/// Using the custom matcher in mock setups (same as built-in Generic matchers):
+///
+/// // Setup a generic method to match only numeric types
+/// mimic.Setup(m => m.ProcessValue<NumericTypeMatcher>(It.IsAny<NumericTypeMatcher>()))
+/// .Returns(true);
+///
+/// // This will match calls like:
+/// // mock.ProcessValue<int>(42);
+/// // mock.ProcessValue<double>(3.14);
+/// // But not:
+/// // mock.ProcessValue<string>("hello");
+///
+/// Combining with the built-in Generic matchers:
+///
+/// // Mix custom and built-in matchers
+/// mimic.Setup(m => m.Convert<Generic.AnyReferenceType, NumericTypeMatcher>())
+/// .Returns("converted");
+///
+///
+///
+///
+///
+///
+///
[PublicAPI]
public interface IGenericMatcher
{
+ ///
+ /// Determines whether the specified generic type matches the criteria defined by this matcher.
+ ///
+ /// The generic type argument to evaluate for matching.
+ ///
+ /// true if the specified satisfies the matching criteria;
+ /// otherwise, false.
+ ///
+ ///
+ /// This method is called by the Mimic framework during mock setup and verification to determine
+ /// if a generic type argument matches the expectations defined by the implementing matcher.
+ /// The implementation should be efficient as it may be called frequently during mock operations.
+ ///
+ ///
+ ///
+ /// public bool Matches(Type genericType)
+ /// {
+ /// // Example: Match only types that implement IComparable
+ /// return typeof(IComparable).IsAssignableFrom(genericType);
+ /// }
+ ///
+ ///
bool Matches(Type genericType);
}
diff --git a/src/Mimic/IMimicked`1.cs b/src/Mimic/IMimicked`1.cs
index a9dfade..5e75fb9 100644
--- a/src/Mimic/IMimicked`1.cs
+++ b/src/Mimic/IMimicked`1.cs
@@ -1,9 +1,19 @@
namespace Mimic;
+///
+/// Represents an interface for accessing the underlying mimic instance for a mocked object.
+///
+/// The type being mocked, which must be a reference type.
[PublicAPI]
[EditorBrowsable(EditorBrowsableState.Never)]
public interface IMimicked
where T : class
{
+ ///
+ /// Gets the instance associated with the mocked object.
+ ///
+ ///
+ /// The mimic instance that controls the behaviour and verification of the mocked object.
+ ///
Mimic Mimic { get; }
}
diff --git a/src/Mimic/Mimic`1.Setup.cs b/src/Mimic/Mimic`1.Setup.cs
index 54643c1..b689d28 100644
--- a/src/Mimic/Mimic`1.Setup.cs
+++ b/src/Mimic/Mimic`1.Setup.cs
@@ -7,18 +7,39 @@ namespace Mimic;
public partial class Mimic
{
+ ///
+ /// Sets up a method or property on the mocked object to be configured with behaviours.
+ ///
+ /// An expression that specifies the method or property to set up.
+ /// An that can be used to configure the behaviour of the specified method or property.
+ /// Thrown when is null.
public ISetup Setup(Expression> expression)
{
var setup = Setup(this, expression);
return new Setup(setup);
}
+ ///
+ /// Sets up a method or property on the mocked object that returns a value to be configured with behaviours.
+ ///
+ /// The type of the return value of the method or property being set up.
+ /// An expression that specifies the method or property to set up.
+ /// An that can be used to configure the behaviour and return value of the specified method or property.
+ /// Thrown when is null.
public ISetup Setup(Expression> expression)
{
var setup = Setup(this, expression);
return new Setup(setup);
}
+ ///
+ /// Sets up a property getter on the mocked object to be configured with behaviours.
+ ///
+ /// The type of the property being set up.
+ /// An expression that specifies the property getter to set up.
+ /// An that can be used to configure the behaviour of the specified property getter.
+ /// Thrown when is null.
+ /// Thrown when the expression does not represent a property or the property cannot be read.
public IGetterSetup SetupGet(Expression> expression)
{
Guard.NotNull(expression);
@@ -36,6 +57,13 @@ public IGetterSetup SetupGet(Expression(setup);
}
+ ///
+ /// Sets up a property setter on the mocked object to be configured with behaviours.
+ ///
+ /// An action that specifies the property setter to set up.
+ /// An that can be used to configure the behaviour of the specified property setter.
+ /// Thrown when is null.
+ /// Thrown when the expression does not represent a valid property setter.
public ISetup SetupSet(Action setterExpression)
{
Guard.NotNull(setterExpression);
@@ -47,6 +75,14 @@ public ISetup SetupSet(Action setterExpression)
return new Setup(setup);
}
+ ///
+ /// Sets up a property setter on the mocked object to be configured with behaviours, with strongly typed property support.
+ ///
+ /// The type of the property being set up.
+ /// An action that specifies the property setter to set up.
+ /// An that can be used to configure the behaviour of the specified property setter.
+ /// Thrown when is null.
+ /// Thrown when the expression does not represent a valid property setter.
public ISetterSetup SetupSet(Action setterExpression)
{
Guard.NotNull(setterExpression);
@@ -58,6 +94,15 @@ public ISetterSetup SetupSet(Action setterExpression
return new SetterSetup(setup);
}
+ ///
+ /// Sets up a property on the mocked object to behave like a real property with automatic getter and setter behaviour.
+ ///
+ /// The type of the property being set up.
+ /// An expression that specifies the property to set up.
+ /// The initial value to assign to the property. Defaults to the default value of .
+ /// The current instance for method chaining.
+ /// Thrown when is null.
+ /// Thrown when the expression does not represent a property, or the property cannot be read or written.
public Mimic SetupProperty(Expression> propertyExpression, TProperty? initialValue = default)
{
Guard.NotNull(propertyExpression);
@@ -81,6 +126,10 @@ public Mimic SetupProperty(Expression> property
return this;
}
+ ///
+ /// Sets up all properties on the mocked object to behave like real properties with automatic getter and setter behaviour.
+ ///
+ /// The current instance for method chaining.
public Mimic SetupAllProperties()
{
_setups.Add(new AllPropertiesStubSetup(this));
diff --git a/src/Mimic/Mimic`1.VerifyReceived.cs b/src/Mimic/Mimic`1.VerifyReceived.cs
index f17b220..11d0d44 100644
--- a/src/Mimic/Mimic`1.VerifyReceived.cs
+++ b/src/Mimic/Mimic`1.VerifyReceived.cs
@@ -5,10 +5,20 @@ namespace Mimic;
public partial class Mimic
{
+ ///
+ /// Verifies that the mimic has received all expected setups.
+ ///
public void VerifyExpectedReceived() => VerifyReceived(s => s.Expected, []);
+ ///
+ /// Verifies that the mimic has received all configured setups.
+ ///
public void VerifyAllSetupsReceived() => VerifyReceived((SetupBase _) => true, []);
+ ///
+ /// Verifies that the mimic has received no other calls beyond those already verified.
+ ///
+ /// Thrown when unverified invocations are found.
public void VerifyNoOtherCallsReceived()
{
lock (_invocations)
@@ -21,15 +31,43 @@ public void VerifyNoOtherCallsReceived()
#region VerifyReceived
+ ///
+ /// Verifies that the specified method call expression was received at least once.
+ ///
+ /// The expression representing the method call to verify.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation was not received.
public void VerifyReceived(Expression> expression) =>
VerifyReceivedInternal(expression, CallCount.AtLeastOnce());
+ ///
+ /// Verifies that the specified method call expression was received the expected number of times.
+ ///
+ /// The expression representing the method call to verify.
+ /// The expected number of calls.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation count was not met.
public void VerifyReceived(Expression> expression, CallCount callCount) =>
VerifyReceivedInternal(expression, callCount);
+ ///
+ /// Verifies that the specified method call expression was received at least once, with a custom failure message.
+ ///
+ /// The expression representing the method call to verify.
+ /// The custom message to display when verification fails.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation was not received.
public void VerifyReceived(Expression> expression, string failureMessage) =>
VerifyReceivedInternal(expression, CallCount.AtLeastOnce(), failureMessage);
+ ///
+ /// Verifies that the specified method call expression was received the expected number of times, with a custom failure message.
+ ///
+ /// The expression representing the method call to verify.
+ /// The expected number of calls.
+ /// The custom message to display when verification fails.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation count was not met.
public void VerifyReceived(Expression> expression, CallCount callCount, string failureMessage) =>
VerifyReceivedInternal(expression, callCount, failureMessage);
@@ -37,15 +75,47 @@ public void VerifyReceived(Expression> expression, CallCount callCount
#region VerifyReceived
+ ///
+ /// Verifies that the specified method call expression returning a value was received at least once.
+ ///
+ /// The return type of the method being verified.
+ /// The expression representing the method call to verify.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation was not received.
public void VerifyReceived(Expression> expression) =>
VerifyReceivedInternal(expression, CallCount.AtLeastOnce());
+ ///
+ /// Verifies that the specified method call expression returning a value was received the expected number of times.
+ ///
+ /// The return type of the method being verified.
+ /// The expression representing the method call to verify.
+ /// The expected number of calls.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation count was not met.
public void VerifyReceived(Expression> expression, CallCount callCount) =>
VerifyReceivedInternal(expression, callCount);
+ ///
+ /// Verifies that the specified method call expression returning a value was received at least once, with a custom failure message.
+ ///
+ /// The return type of the method being verified.
+ /// The expression representing the method call to verify.
+ /// The custom message to display when verification fails.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation was not received.
public void VerifyReceived(Expression> expression, string failureMessage) =>
VerifyReceivedInternal(expression, CallCount.AtLeastOnce(), failureMessage);
+ ///
+ /// Verifies that the specified method call expression returning a value was received the expected number of times, with a custom failure message.
+ ///
+ /// The return type of the method being verified.
+ /// The expression representing the method call to verify.
+ /// The expected number of calls.
+ /// The custom message to display when verification fails.
+ /// Thrown when the expression is null.
+ /// Thrown when the expected invocation count was not met.
public void VerifyReceived(Expression> expression, CallCount callCount, string failureMessage) =>
VerifyReceivedInternal(expression, callCount, failureMessage);
@@ -53,15 +123,43 @@ public void VerifyReceived(Expression> expression, Cal
#region VerifyGetReceived
+ ///
+ /// Verifies that the specified property getter was accessed at least once.
+ ///
+ /// The type of the property being verified.
+ /// The expression representing the property getter to verify.
+ /// Thrown when the expression is not a valid property getter or when the expected access was not received.
public void VerifyGetReceived(Expression> expression) =>
VerifyGetReceivedInternal(expression, CallCount.AtLeastOnce());
+ ///
+ /// Verifies that the specified property getter was accessed the expected number of times.
+ ///
+ /// The type of the property being verified.
+ /// The expression representing the property getter to verify.
+ /// The expected number of accesses.
+ /// Thrown when the expression is not a valid property getter or when the expected access count was not met.
public void VerifyGetReceived(Expression> expression, CallCount callCount) =>
VerifyGetReceivedInternal(expression, callCount);
+ ///
+ /// Verifies that the specified property getter was accessed at least once, with a custom failure message.
+ ///
+ /// The type of the property being verified.
+ /// The expression representing the property getter to verify.
+ /// The custom message to display when verification fails.
+ /// Thrown when the expression is not a valid property getter or when the expected access was not received.
public void VerifyGetReceived(Expression> expression, string failureMessage) =>
VerifyGetReceivedInternal(expression, CallCount.AtLeastOnce(), failureMessage);
+ ///
+ /// Verifies that the specified property getter was accessed the expected number of times, with a custom failure message.
+ ///
+ /// The type of the property being verified.
+ /// The expression representing the property getter to verify.
+ /// The expected number of accesses.
+ /// The custom message to display when verification fails.
+ /// Thrown when the expression is not a valid property getter or when the expected access count was not met.
public void VerifyGetReceived(Expression> expression, CallCount callCount, string failureMessage) =>
VerifyGetReceivedInternal(expression, callCount, failureMessage);
@@ -69,15 +167,43 @@ public void VerifyGetReceived(Expression> expressi
#region VerifySetReceived
+ ///
+ /// Verifies that the specified property setter was called at least once.
+ ///
+ /// The expression representing the property setter to verify.
+ /// Thrown when setterExpression is null.
+ /// Thrown when the expression is not a valid property setter or when the expected call was not received.
public void VerifySetReceived(Action setterExpression) =>
VerifySetReceivedInternal(setterExpression, CallCount.AtLeastOnce());
+ ///
+ /// Verifies that the specified property setter was called the expected number of times.
+ ///
+ /// The expression representing the property setter to verify.
+ /// The expected number of calls.
+ /// Thrown when setterExpression is null.
+ /// Thrown when the expression is not a valid property setter or when the expected call count was not met.
public void VerifySetReceived(Action setterExpression, CallCount callCount) =>
VerifySetReceivedInternal(setterExpression, callCount);
+ ///
+ /// Verifies that the specified property setter was called at least once, with a custom failure message.
+ ///
+ /// The expression representing the property setter to verify.
+ /// The custom message to display when verification fails.
+ /// Thrown when setterExpression is null.
+ /// Thrown when the expression is not a valid property setter or when the expected call was not received.
public void VerifySetReceived(Action setterExpression, string failureMessage) =>
VerifySetReceivedInternal(setterExpression, CallCount.AtLeastOnce(), failureMessage);
+ ///
+ /// Verifies that the specified property setter was called the expected number of times, with a custom failure message.
+ ///
+ /// The expression representing the property setter to verify.
+ /// The expected number of calls.
+ /// The custom message to display when verification fails.
+ /// Thrown when setterExpression is null.
+ /// Thrown when the expression is not a valid property setter or when the expected call count was not met.
public void VerifySetReceived(Action setterExpression, CallCount callCount, string failureMessage) =>
VerifySetReceivedInternal(setterExpression, callCount, failureMessage);
diff --git a/src/Mimic/Mimic`1.cs b/src/Mimic/Mimic`1.cs
index 646a104..7c008a1 100644
--- a/src/Mimic/Mimic`1.cs
+++ b/src/Mimic/Mimic`1.cs
@@ -17,10 +17,29 @@ public sealed partial class Mimic : IMimic
private object[]? _constructorArguments;
private T? _object;
+ ///
+ /// Gets the unique name identifier for this mimic instance.
+ ///
+ /// A string representing the mimic's name in the format "Mimic<TypeName>:InstanceNumber".
public string Name { get; init; }
+ ///
+ /// Gets a value indicating whether this mimic operates in strict mode.
+ ///
+ /// true if the mimic is in strict mode; otherwise, false. The default value is true.
+ ///
+ /// In strict mode, the mimic will enforce that all method calls have corresponding setups.
+ ///
public bool Strict { get; init; } = true;
+ ///
+ /// Gets or sets the constructor arguments to be used when creating the mimicked object.
+ ///
+ /// An array of objects to be passed as constructor arguments, or null if no arguments are needed.
+ /// Thrown when attempting to set constructor arguments for an interface type.
+ ///
+ /// Constructor arguments should only be provided when mimicking concrete classes, not interfaces.
+ ///
public object[]? ConstructorArguments
{
get => _constructorArguments;
@@ -33,6 +52,13 @@ public object[]? ConstructorArguments
}
}
+ ///
+ /// Gets the mimicked object instance.
+ ///
+ /// The proxy object that implements the behaviour defined by the mimic setups.
+ ///
+ /// The object is lazily initialised upon first access. Subsequent calls return the same instance.
+ ///
public T Object => GetOrInitializeObject();
internal IReadOnlyList Invocations
@@ -40,6 +66,13 @@ internal IReadOnlyList Invocations
get { lock (_invocations) return _invocations.ToArray(); }
}
+ ///
+ /// Initialises a new instance of the class with strict mode enabled.
+ ///
+ /// Thrown when the type cannot be mimicked.
+ ///
+ /// The mimic will operate in strict mode by default, requiring all method calls to have corresponding setups.
+ ///
public Mimic()
{
if (!typeof(T).CanBeMimicked())
@@ -49,8 +82,27 @@ public Mimic()
Name = $"Mimic<{TypeNameFormatter.GetFormattedName(typeof(T))}>:{instanceNumber}";
}
+ ///
+ /// Initialises a new instance of the class with the specified strict mode setting.
+ ///
+ /// true to enable strict mode; false to disable it.
+ /// Thrown when the type cannot be mimicked.
+ ///
+ /// In strict mode, all method calls must have corresponding setups. In non-strict mode,
+ /// method calls without setups will return default values or perform no action.
+ ///
public Mimic(bool strict) : this() => Strict = strict;
+ ///
+ /// Retrieves the mimic instance from an object that was created by a mimic.
+ ///
+ /// The object instance that was created by a mimic.
+ /// The instance that created the specified object.
+ /// Thrown when the provided object was not created by a mimic.
+ ///
+ /// This method allows you to get the original mimic instance from a mimicked object,
+ /// which is useful for verification or additional setup operations.
+ ///
public static Mimic FromObject(T objectInstance)
{
if (objectInstance is not IMimicked mimicked)
@@ -59,8 +111,21 @@ public static Mimic FromObject(T objectInstance)
return mimicked.Mimic;
}
+ ///
+ /// Creates a conditional setup that applies only when the specified condition is met.
+ ///
+ /// A function that returns true when the conditional setup should be active.
+ /// An that can be used to define behaviour for the conditional setup.
+ ///
+ /// Conditional setups allow you to define different behaviours based on runtime conditions.
+ /// The condition is evaluated each time a matching method is called.
+ ///
public IConditionalSetup When(Func condition) => new ConditionalSetup(this, condition);
+ ///
+ /// Returns a string representation of this mimic instance.
+ ///
+ /// The name of this mimic instance.
public override string ToString() => Name;
private T GetOrInitializeObject()