Telerik® JustMock™ by Progress

Matchers let you ignore passing actual values as arguments used in mocks. Instead, they give you the possibility to pass just an expression that satisfies the argument type or the expected value range. For example, if a method accepts a string as a first parameter, you don’t need to pass a specific string like "Camera". Instead, you can use Arg.IsAny<string>(). There are several types of matchers supported in Telerik JustMock:

  1. Defined Matchers (Arg.AnyBool, Arg.AnyDouble, Arg.AnyFloat, Arg.AnyGuid, Arg.AnyInt, Arg.AnyLong, Arg.AnyObject, Arg.AnyShort, Arg.AnyString, Arg.NullOrEmpty)
  2. Arg.IsAny<T>();
  3. Arg.IsInRange([FromValue : int], [ToValue : int], [RangeKind])
  4. Arg.Matches<T>(Expression<Predicate<T>> expression)
  5. Arg.Ref()

Matchers also let you ignore all arguments in your mocks by a single call to IgnoreArguments() (in the arrangement) or Args.Ignore() (in the assertion).

To take a look at each one of these features in details, we will use the following interfaces:

Arg.IsAny<T>();

We've already used this matcher in one of our examples earlier.

C# Copy imageCopy
Mock.Arrange(() => warehouse.HasInventory(Arg.IsAny<string>(), Arg.IsAny<int>())).Returns(true);

Visual Basic Copy imageCopy
Mock.Arrange(Function() warehouse.HasInventory(Arg.IsAny(Of String)(), Arg.IsAny(Of Integer)())).Returns(True)

This matcher specifies that when the HasInventory method is called with any string as a first argument and any int as a second it should return true.

Arg.IsInRange(int from, int to, RangeKind range)

The IsInRange matcher lets us arrange a call for an expected value range. With the RangeKind argument we can specify whether the given range includes or excludes its boundaries.

Consider the following example:

C# Copy imageCopy
Mock.Arrange(() => foo.Echo(Arg.IsInRange(0, 5, RangeKind.Inclusive))).Returns(true);

Visual Basic Copy imageCopy
Mock.Arrange(Function() foo.Echo(Arg.IsInRange(0, 5, RangeKind.Inclusive))).Returns(True)

With the first line we specify that when the foo.Echo method is called with an argument value ranging from 0 to 5, the method will return true. We specify the RangeKind to be Inclusive which means that calling the method with 0 or 5 satisfies the range condition and it will return true for these values.

C# Copy imageCopy
Mock.Arrange(() => foo.Echo(Arg.IsInRange(0, 5, RangeKind.Exclusive))).Returns(true);

Visual Basic Copy imageCopy
Mock.Arrange(Function() foo.Echo(Arg.IsInRange(0, 5, RangeKind.Exclusive))).Returns(True)

On the second line we specify the RangeKind to be Exclusive so calling the method with 6 or 10 doesn’t satisfy the condition because these values are excluded from the range.

Arg.Matches<T> (Expression<Predicate<T>> expression)

This is the most flexible matcher and it allows you to specify your own matching expression. Let's illustrate it with a simple example:

C# Copy imageCopy
Mock.Arrange(() => foo.Echo(Arg.Matches<int>( x => x < 10)).Returns(true);

Visual Basic Copy imageCopy
Mock.Arrange(Function() foo.Echo(Arg.Matches(Of Integer)(Function(x) x < 10))).Returns(True)

With our expression (or predicate) x => x < 10 we specify that a call to foo.Echo with an argument less than 10 should return true.

Ignoring All Arguments in Arrangement

To set argument independent expectations against certain method, you have to apply IgnoreArguments to its arrangement. The next example explains this functionality:

After creating mock of the IFoo, we arrange that every Echo call, no matter its arguments should return 10. For this, in the arrangement we pass arguments from their corresponding types and then we apply the IgnoreArguments functionality.

Using Matchers in Assert

Matchers are also useful in assertion. Consider a fictitious payment service where we don't care what the payment date is, but we want to make sure that the payment amount which is passed to the service is $54.44. We can easily achieve this by using the following statement:

We assert for calling ProcessPayment with whatever DateTime argument and payment amount exactly $54.44.

Here is another example. We specify that an Echo call with arguments 10 and 20 should return 30. We use the matchers Arg.Matches<int>(x => x == 10) and Arg.Matches<int>(x => x == 20) to handle the case when we pass 10 and 20 to the Echo method.

Using Matchers to Ignore All Arguments in Assert

You already saw how you can use matchers in your assertion calls. If you need you can specify that you want to ignore all arguments in the assert call. You do this by adding the Args.Ignore() argument to the Mock.Assert call. Here is an example:

In this way we assert for calling ProcessPayment no matter the arguments.

Using Matchers and Specializations

In an arrangement you can define more than one matcher. Consider the following example:

In the case when a specialization is used among with Arg.IsAny<T>, JustMock will select the arrangement with the proper matcher. foo.Echo(1) will use the first matcher and will return 10. But foo.Echo(11) will use the second matcher because it is a specialization of the first and applies the call, therefore ArgumentException will be thrown.

Using Matchers for ref Arguments (Arg.Ref())

Note

Arg.Ref is used only in C# assemblies, as for Visual Basic you can directly match ByRef arguments without it.

With Telerik JustMock you are now able to use matchers for functions that take ref arguments. For this purpose, you need to use the Arg.Ref().Value syntax. Check the next examples for further guidance:

  • Here we will use the Arg.Ref matcher, in order to match function that will be called with a ref argument with known value.

    Note, the using of the Value field at the end of the matcher (Arg.Ref(5).Value) is intended and needed in order to use this feature.

  • Here we will use the Arg.Ref matcher, in order to match function that will be called with a ref argument with known type. To match the type, we will use a defined matcher.

    Note, the using of the Value field at the end of the matcher (Arg.Ref(Arg.AnyInt).Value) is intended and needed in order to use this feature.

  • Here we will use the Arg.Ref matcher, in order to match function that will be called with a ref argument with known type and value interval. We will use Arg.Matches<T>() for this.

    Note, the using of the Value field at the end of the matcher (Arg.Ref(Arg.Matches<int>(x => x > 10)).Value) is intended and needed in order to use this feature.

See Also

Other Resources