New to Telerik JustMockStart a free 30-day trial

RecursiveLoose

Updated on Mar 25, 2026

RecursiveLoose is the default mock behavior. For any property or method that returns a reference type, RecursiveLoose automatically returns a new mock (also with Behavior.RecursiveLoose), so you can chain calls on returned mocks without arranging each level.

For types that cannot be mocked (string, int, and other value types), RecursiveLoose returns default values. For string it returns an empty string. For collection return types (for example, arrays or IEnumerable), it returns a non-null empty collection.

RecursiveLoose is identical to Loose mocks except that it auto-generates mocks for reference-type members at every level of the object graph. This eliminates the need to arrange the full call chain manually. You can override any member's behavior by adding an explicit arrangement, as described in the JustMock API Basics articles.

RecursiveLoose is the default behavior when creating mocks.

Syntax

As this is every mocks default behavior, its enough to write - Mock.Create<T>();. The RecursiveLoose behavior will be applied automatically.

To explicitly set Behavior.RecursiveLoose use Mock.Create<T>(Behavior.RecursiveLoose);

Examples

The Difference Between RecursiveLoose and Loose Mocks

To explain what differs between both behaviors, let's look at the following interface:

C#
public interface IFirst
{
    ISecond Second { get; set; }
}
public interface ISecond
{
    IThird Third { get; set; }
}

public interface IThird
{
    IFourth Fourth { get; set; }
    Task<IFourth> GetFourthAsync();
}

public interface IFourth
{
    string DoSomething();
}

Here, we have a number of nested properties. If we try to call a low level, non-arranged function from a Loose mock, the test will throw a NullReferenceException. This is shown in the next example:

C#
[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void ShouldAssertAgainstNonArrangedChainCallInLooseMock()
{
    //Arrange
    var foo = Mock.Create<IFirst>(Behavior.Loose);

    //Act
    foo.Second.Third.Fourth.DoSomething(); // This will throw a NullReferenceException
}

The exception is thrown right after the initialization of the Second property, as it returns the default reference type value (null). To avoid this in a Loose mock, we need to arrange the method chain, like this:

C#
[TestMethod]
public void ShouldAssertAgainstArrangedChainCallInLooseMock()
{
    //Arrange
    var foo = Mock.Create<IFirst>(Behavior.Loose);

    Mock.Arrange(() => foo.Second.Third.Fourth.DoSomething()).Returns(String.Empty);

    //Act
    var actual = foo.Second.Third.Fourth.DoSomething();

    // Assert
    Assert.IsNotNull(actual);
}

Using RecursiveLoose mocks, we are capable of writing the following:

C#
[TestMethod]
public void ShouldAssertAgainstNonArrangedChainCallInRecursiveLooseMock()
{
    //Arrange
    var foo = Mock.Create<IFirst>(Behavior.RecursiveLoose); // This equals to: Mock.Create<IFirst>();

    //Act
    var actual = foo.Second.Third.Fourth.DoSomething();

    // Assert
    Assert.IsNotNull(actual);
}

Notice that no additional arrangements are needed for the test to pass.

Using RecursiveLoose Mocks in Your Tests

Assume we have the next system under test:

C#
public class Product
{

}

public class Order
{
    public List<Product> Products
    {
        get { return products; }
    }

    private List<Product> products;
}

public class OrderRepository
{
    public Order Order
    {
        get { return order; }
    }

    private Order order;
}

public class ClassUnderTest
{
    public OrderRepository Repo
    {
        get { return new OrderRepository(); }
    }

    public string MethodUnderTest()
    {
        if (Repo.Order.Products != null)
        {
            return "Pass";
        }

        return "Fail";
    }
}

To enter the If statement of the MethodUnderTest(), we simply need to pass a RecursiveLoose mock, like this:

C#
[TestMethod]
public void ShouldReturnRecursiveMock()
{
    var cut = new ClassUnderTest();

    // Arrange
    Mock.Arrange(() => cut.Repo).Returns(Mock.Create<OrderRepository>());

    // Act
    var actual = cut.MethodUnderTest();

    // Assert
    Assert.AreEqual("Pass", actual);
}

RecursiveLoose Mocks in Async Tests

The RecursiveLoose behavior automatically intercepts the return types in asynchronous calls and returns a mock object:

C#
[TestMethod]
public async Task ShouldAssertAgainstNonArrangedChainCallInRecursiveLooseMockAsync()
{
    //Arrange
    var foo = Mock.Create<IFirst>(Behavior.RecursiveLoose); // This equals to: Mock.Create<IFirst>();

    //Act
    var actual = await foo.Second.Third.GetFourthAsync();

    // Assert
    Assert.IsNotNull(actual.DoSomething());
}

In some scenarios returning mock objects on asynchronous calls might lead to undesired behavior during acting phase, consider the cases when the return type is a system type. The automatic return type interception could be disabled by explicitly using NotIntercept in the following way:

C#
[TestMethod]
[ExpectedException(typeof(NotImplementedException))]
public async Task ShouldThrowAgainstNonArrangedChainCallInRecursiveLooseMockAsync()
{
    //Arrange
    Mock.NotIntercept<IFourth>();
    var foo = Mock.Create<IFirst>(Behavior.RecursiveLoose);

    //Act
    var actual = await foo.Second.Third.GetFourthAsync();

    // Assert
    Assert.IsNull(actual.DoSomething());
}

See Also