When using Microsoft CodeContracts your Contract.Requires and Contract.Ensures statements will throw a ContractException which you cannot catch (per design). This means that you cannot use the [ExceptedException] attribute to assert them.
Furthermore when mocking with Telerik Justock you cannot use Contract.Ensures and Contract.Requires at all in your stubs, as the stub is expected to be a Func in the form of .DoInstead(() => { return something; }).
This means when mocking an underlying function in your code to verify your subject under test, you have to come up with a workaround to mimick that behaviour.
Imagine you have the following functions:
public class HelperClass()
{
public SomeObject HelperFunction(int value)
{
Contract.Requires(0 < value);
Contract.Ensures(null != Contract.Returns<someobject>());</someobject>
// do something against a backend system not reachable from the test environment
var result = HttpClientHelper.Get("https://www.example.com/somewhere");
return new SomeObject(result);
}
}
public class SutClass()
{
public bool SutMethod(int value)
{
var someObject = new HelperClass().SomeObject(value);
return someObject.IsValid();
}
}
In case you want to test your SutClass and HelperClass contains some functionality that you cannot or do not execute within your test environment, your code will fail within the HelperClass and thus your SutMethod cannot be tested like this:
[TestMethod]
public void SutMethodWithInvalidSomeObjectThrows()
{
// Arrange
var sut = new SutClass();
// Act
var result = sut.SutMethod(42);
// Assert
Assert.IsTrue(result);
}
In your test environment your HelperFunction would not throw in Contract.Ensures but already throw while trying to reach the web server. In addition, the exception would probably not be a ContractException but some other exception like WebException.
We can actually bypass this by mocking the SutClass and returning different code that will throw the assertion as expected. We will use Telerik JustMock for this:
[TestMethod]
[ExpectContractException]
public void SutMethodWithInvalidSomeObjectThrows()
{
// Arrange
var sutClass = Mock.Create<sutclass>();
Mock.Arrange(() => sutClass.SutMethod(Arg.IsAny<int>()))
.IgnoreInstance()
.DoInstead(() => { Contract.Assert(null != null); });</int></sutclass>
// Act
var result = sut.SutMethod(42);
// Assert
// no assertion needed as SutMethod is expected to throw
}
With this mock we can actually simulate the exception thrown by Contract.Ensures as Contract.Assert will throw the same exception.
That was easy and we are already at the end of our story … for more information also have a look about our other post about CodeContracts, the ExpectContractException attribute and Telerik JustMock.
