Constraints are a way to verify that a method's arguments match a certain criteria. Rhino Mocks includes a number of built-in constraints, and allows you to define you own custom ones, which will integrate cleanly into the framework. You specify constraints on method arguments using the following syntax:
Expect.Call(view.Ask(null,null)).IgnoreArguments().Constraints(
Is.Anything(), Is.TypeOf(typeof(SomeType))).Return(null).
You need to pass the exact same number of constraints as the number of arguments of the method. When a method is called during replay state, Rhino Mocks evaluates each constraint against the parameter in the same index, and accepts the method if all the constraints were met. As a note, I got the idea of the current constraints syntax from NMock2, as it is much leaner approach to create constraints.
Rhino Mocks' built in constraints:
Rhino Mocks Constraints
| Constraint
|
| Example
| Accepted Values
| Rejected Values
|
| Is | Anything | Is.Anything() | Anything at all {0,"","whatever",null, etc} | Nothing Whatsoever
|
| Equal | Is.Equal(3) | 3 | 5 |
| Not Equal | Is.NotEqual(3) | null, "bar" | 3 |
| Null | Is.Null() | null | 5, new object() |
| Not Null | Is.NotNull() | new object(), DateTime.Now | null |
| Type Of | Is.TypeOf(typeof(Customer)) or Is.TypeOf<Customer>() | myCustomer, new Customer() | null, "str" |
| Greater Than | Is.GreaterThan(10) | 15,53 | 2,10 |
| Greater Than Or Equal | Is.GreaterThanOrEqual(10) | 10,15,43 | 9,3 |
| Less Than | Is.LessThan(10) | 1,2,3,9 | 10,34 |
| Less Than Or Equal | Is.LessThanOrEqual(10) | 10,9,2,0 | 34,53,99 |
| Matching | Is.Matching(Predicate<T>) | | |
| Same | Is.Same(object) | | |
| NotSame | Is.NotSame(object) | | |
| Property | Equal To Value | Property.Value("Length",0) | new ArrayList() | "Hello", null |
| Null | Property.IsNull("InnerException") | new Exception("exception without inner exception") | new Exception("Exception with inner Exception", new Exception("Inner") |
| Not Null | Property.IsNotNull("InnerException") | new Exception("Exception with inner Exception", new Exception("Inner") | new Exception("exception without inner exception") |
| List | Is In List [the parameter is a collection that contains this value] | List.IsIn(4) | new int[]{1,2,3,4}, new int[]{4,5,6} | new object[]{"",3} |
| One Of [parameter equal to one of the objects in this list] | List.OneOf(new int[]{3,4,5}) | 3,4,5 | 9,1,""
|
| Equal | List.Equal(new int[]{4,5,6}) | new int[]{4,5,6}, new object[]{4,5,6} | new int[]{4,5,6,7} |
| Text | Starts With | Text.StartsWith("Hello") | "Hello, World", "Hello, Rhino Mocks" | "", "Bye, Bye" |
| Ends With | Text.EndsWith("World") | "World","Champion Of The World" | "world", "World Seria" |
| Contains | Text.Contains("or") | "The Horror Movie...", "Either that or this" | "Movie Of The Year" |
| Like [Perform regular expression validation] | Text.Like("rhino|Rhinoceros|rhinoceros") | "Rhino Mocks", "Red Rhinoceros" | "Hello world", "Foo bar", Another boring example string" |
EditConstraints Grouping
You can group Rhino Mocks Constraints by using the following operators:
- !|- Not operator
- && - And operator
- || - Or Operator
Grouping constraints is like grouping booleans in a way -- every constraint is checked during mocks verification, and one can say that every constraint, too, evaluates either to true or false. Here is a code snippet along with an explanation to make things sparklingly clear.
public void Test()
{
MockRepository mocks = new MockRepository();
IValidationMessagesLogger loggerMock = mocks.DynamicMock<IValidationMessagesLogger>(null);
using (mocks.Record())
{
loggerMock.LogMessage(null);
LastCall.Constraints(/*LastCall notation is used because LogMessage(...) does not return anything (is void).*/
new PropertyConstraint("Text", Text.Contains("Whoa!")) &&
Property.Value("MessageKind", ValidationMessageKind.Error))
.Repeat.Once();
}//implicitly calls mocks.ReplayAll()
Validator.Validate("input", loggerMock));//a validator that uses logger internally to log validation messages.
mocks.VerifyAll();
}
You can see that constraints are set for argument the LogMessage method is called with. This argument describes a validation message, and is a class that defines two properties: Text (string) and MessageKind (enumeration). For mock verification to pass, the Text property of the only message logged by the Validator must contain the string "Whoa!",
and the MessageKind property' value must be equal to ValidationMessageKind.Error.
EditUsage with Other MethodOptions
Note that RhinoMocks will throw a InvalidOperationException at runtime if you attempt to specify both a constraint AND a callback. Rather than have possibly conflicting criteria in two places, check for parameter constraints in the callback if you're using one.
Up:
Rhino Mocks Documentation
Next:
Rhino Mocks Method Options Interface