RecursiveLoose mocks will return new mocks (with Behavior.RecursiveLoose)
for all members/functions of the mocked type. However, as there are types that cannot be mocked (string,
int, etc.), RecursiveLoose mocks will return default value for all value type
members and empty, non-null stubs for strings. Also, a non-null empty collection will be returned for collection
return types (e.g. array or IEnumerable) .
RecursiveLoose mocks are the same as Loose mocks,
but with one difference: They will automatically generate empty stubs for all mock members, on all levels. This saves time in manually
arranging or initializing all the mock prerequisites (code examples).
Further, you can change the pre-arranged behavior by defining new expectations, as described in the
RecursiveLoose is the default behavior when creating mocks.
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 -
The Difference Between RecursiveLoose and Loose Mocks
To explain what differs between both behaviors, let's look at the following interface:
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:
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:
Using RecursiveLoose mocks, we are capable of writing the following:
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:
To enter the If statement of the MethodUnderTest(), we simply need to pass a
RecursiveLoose mock, like this:
The RecursiveLoose behavior understands Task<TResult> return types and automatically arranges that awaiting a task
returns a mock: