Question

I would like to write unit test that verify that my method does not accept invalid arguments. Validity of arguments is checked using Code Contract's Contract.Requires call. Why would I want to test contracts? I consider my tests to be kind of method specification (that is actually idea taken from TDD) so by testing that the method fails for some arguments I specify that such arguments should not be used.

The problem is that since I started to use Code contracts I cannot test method contracts because I cannot access the exception that is thrown by Contract.Requires. I can catch generic Exception but that just is not nice... Is there recommended/supported way how to test contract set using Code Contracts?

Seems to me that Code Contracts does not really support unit testing...


EDIT: My test example (I am forced to catch generic exception)

[ExpectedException(typeof(Exception), AllowDerivedTypes = true)]
public void Compute_Throws_ForNullArgument()
{
    new ComputingService().Compute(null);
}

No correct solution

OTHER TIPS

You can hook into the Contract.ContractFailed event.

http://msdn.microsoft.com/en-us/library/system.diagnostics.contracts.contract.contractfailed(v=vs.110).aspx

This will be raised before the exception is thrown. You can combine this with catching Exception to be pretty certain that it represented a contract failure

public void VerifyContract(Action action) { 
  bool failed = false;
  bool thrown = false;
  EventHandler e = (sender, e) => { failed = true; }
  Contract.ContractFailed += e;
  try { 
    action();
  } catch (Execption) {
    Assert.True(failed);
    thrown = true;
  } finally {
    Contract.ContractFailed -= e;
  }
  Assert.True(thrown);
}

You can't explicitly catch the right exception type, but you could catch Exception and then check that it's a ContractException using reflection (rethrowing otherwise).

That would be ugly to do everywhere, but you just need to do it once:

public static void AssertContractFailure(Action action)
{
    try
    {
        action();
        Assert.Fail("Expected contract violation");
    }
    catch (Exception e)
    {
        if (...) // I can't remember offhand what you'd need to check
        {
            throw;
        }
    }
}

Then:

AssertContractFailure(() => SomeContractViolation(...));

Currently if you have that in a helper class you'd need to qualify the call everywhere, but as of C# 6 you'll hopefully be able to import it easily :)

If I recall correctly, contracts throw exceptions if the Requires construct fails, and if the Return construct fails. Therefore surely for unit-testing purposes you simply need to catch these exceptions and you'll know if the contract was violated or not.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top