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.