JustMock

This topic will guide you through couple of simple steps to enable easier testing of your applications by using Telerik JustMock. You will understand a simple principle called Arrange/Act/Assert and get familiar with core methods and properties from the framework, which are useful in the most common testing scenarios.

To use Telerik JustMock in your test projects you first need to add a reference to the Telerik.JustMock.dll assembly (Telerik.JustMock.Silverlight.dll in case of a Silverlight project). This assembly is located in the folder you installed Telerik JustMock under Libraries (by default C:\Program Files\Telerik\JustMock\Libraries\). Remember to include the Telerik.JustMock namespace in the test file.

To illustrate the use of Telerik JustMock in the next examples we will use a sample warehouse and a dependant order object. The warehouse holds inventories of different products. An order contains a product and a quantity. The warehouse interface and the order class look like this:

To execute the tests we use a Test Project inside Visual Studio 2010 (you can use an earlier version of Visual Studio as well).

Arrange / Act / Assert

Arrange Act Assert (AAA) is a pattern for arranging and formatting code in Unit Test methods.

It is used in all samples shown in this documentation. Refer to the Arrange Act Assert topic to learn about AAA.

Methods

Until now we saw how to create mock instance with Mock.Create<>, how to arrange with Mock.Arrange and how to assert with Mock.Assert. We also used two methods - Returns and MustBeCalled in the arrange step. There are a number of handy methods we can use to make our tests more complete and easy to write.

DoInstead

You can use the DoInstead method when you want to change the behavior of a method when it is called by replacing it with a custom action. Let's use the example from above to illustrate to use of DoInstead.

Let's put it simple – we arrange that when the warehouse’s HasInventory method is called with parameters "Camera" and 2 we will execute the action "() => called = true" instead of calling the actual method.

Read more about DoInstead.

CallOriginal

In some cases you may want to arrange to call the original method implementation when it is called with a specific value and to call the mock with other values. For this we can use the CallOriginal method.

In this example we arrange that when order.Receipt method is called with argument DateTime.Today then the original method implementation should be called. But once the same method is called with a date later than DateTime.Today then we return "Invalid date".

DoNothing

For arranging a void call it is a good practice to explicitly mark the mock with DoNothing. Basically it is just a syntactic sugar and does nothing, as the name suggests, but improves the readability of your code. Lets see it in practice.

The first and the second line are functionally the same, but specifying explicitly that setting this property returns nothing makes the code more readable.

Throws

The Throws method is used when you want to throw an exception for a particular method invocation. In the following example, we are throwing an invalid operation exception for trying to call warehouse.Remove with zero quantity.

In this case we use the ExpectedException attribute from Microsoft.VisualStudio.TestTools.UnitTesting to verify that exception of type InvalidOperationException is thrown.

Matchers

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 expected value range. For example, if a method accepts 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 3 types of matchers supported in Telerik JustMock:

  1. Arg.IsAny<[Type]>();
  2. Arg.IsInRange([FromValue : int], [ToValue : int], [RangeKind])
  3. Arg.Matches<T>(Expression<Predicate<T>> expression)

Let's look at each one of them in details.

Arg.IsAny<T>();

We already used this matcher in one of our examples above.

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 let 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.

For argument values ranging from 0 to 5, the following will return true:

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)

For argument values ranging from 1 to 4, the following will return true:

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)

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.

Properties

In the above examples we mock only methods, but you can also mock properties in the same way.

Additionally we can also have some more fun with properties. For example, we can assert for property set.

In the arrange step we set up that the warehouse manager can only be set to "John". But in the act step we set the manager to "Scott". That throws a mock exception. Have in mind that this will only work if you create your mock with StrictBehavior.

Another commonly used technique is to assert that setting a property to a specific value throws an exception. Let's arrange this:

Here we used the Throws method discussed above to indicate that an exception should be thrown if the warehouse.Manager is set to "John".

Events

The method Raises allows you to raise an event when a method is called and to pass specific event arguments. Returning on our warehouse example, we may want to raise the ProductRemoved event once the Remove method is called.

CopyC#
[TestMethod]
public void RaisingAnEvent_TestMethod()
{
    // Arrange
    var warehouse = Mock.Create<Iwarehouse>();

    Mock.Arrange(() => warehouse.Remove(Arg.IsAny<string>(), Arg.IsInRange(int.MinValue, int.MaxValue, RangeKind.Exclusive)))
        .Raises(() => warehouse.ProductRemoved += null, "Camera", 2);

    string productName = string.Empty;
    int quantity = 0;

    warehouse.ProductRemoved += (p, q) => { productName = p; quantity = q; };

    // Act
    warehouse.Remove(Arg.AnyString, Arg.AnyInt);

    // Assert
    Assert.AreEqual("Camera", productName);
    Assert.AreEqual(2, quantity);
}

Here in the arrange step we set up that once the warehouse’s Remove method is called we will raise the ProductRemoved event with parameters "Camera" and 2.

Wrapper Of Framework Assert

In the examples in this topic we have used the framework assertion that is available when a reference to the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll is added to the project. In most of the examples in the further topics a wrapper of the framework assert that exposes xUnit alike methods is used.

With the following using directive

using FrameworkAssert = Microsoft.VisualStudio.TestTools.UnitTesting.Assert;

the wrapper is defined as:

C# Copy imageCopy
public static class Assert
{
    public static Exception Throws<T>( Action action ) where T : Exception
    {
        Exception targetException = null;

        try
        {
            action();
            FrameworkAssert.Fail( "No Expected " + typeof( T ).FullName + " was thrown" );
        }
        catch ( T ex )
        {
            targetException = ex;
        }
        return targetException;
    }

    public static void NotNull( object value )
    {
        FrameworkAssert.IsNotNull( value );
    }

    public static void Null( object value )
    {
        FrameworkAssert.IsNull( value );
    }

    public static void Equal<T>( T expected, T actual )
    {
        FrameworkAssert.AreEqual( expected, actual );
    }

    public static void NotEqual<T>( T notExpected, T actual )
    {
        FrameworkAssert.AreNotEqual( notExpected, actual );
    }

    public static void True( bool condition )
    {
        FrameworkAssert.IsTrue( condition );
    }

    public static void False( bool condition )
    {
        FrameworkAssert.IsFalse( condition );
    }

    public static void Same( object expected, object actual )
    {
        FrameworkAssert.AreSame( expected, actual );
    }
}

CopyC#
public static class Assert
{
    public static Exception Throws<T>( Action action ) where T : Exception
    {
        Exception targetException = null;

        try
        {
            action();
            FrameworkAssert.Fail( "No Expected " + typeof( T ).FullName + " was thrown" );
        }
        catch ( T ex )
        {
            targetException = ex;
        }
        return targetException;
    }

    public static void NotNull( object value )
    {
        FrameworkAssert.IsNotNull( value );
    }

    public static void Null( object value )
    {
        FrameworkAssert.IsNull( value );
    }

    public static void Equal<T>( T expected, T actual )
    {
        FrameworkAssert.AreEqual( expected, actual );
    }

    public static void NotEqual<T>( T notExpected, T actual )
    {
        FrameworkAssert.AreNotEqual( notExpected, actual );
    }

    public static void True( bool condition )
    {
        FrameworkAssert.IsTrue( condition );
    }

    public static void False( bool condition )
    {
        FrameworkAssert.IsFalse( condition );
    }

    public static void Same( object expected, object actual )
    {
        FrameworkAssert.AreSame( expected, actual );
    }
}

Additionally, with Telerik JustMock installed you receive a sample project that uses this wrapper of the framework assertion. Refer to the project for further information on how to use the Assert wrapper in your tests.

See Also