I am new to contracts and I took from the overview that it could help you at compile time to discover contract violations.
I am not getting a compile time warning or error when I have code that explicitly violates a contract.
I would expect the line of code in the test that sets Person.Name = null
would give me a warning or an error, since it violates the contract.
How can I adjust my code to get compile time messages?
Note: To clarify, the only reason I put it in a unit test was to get a compile time message. The test itself currently passes and that is a run-time aspect; I guess it should pass since it's a compile time test not a run-time test. Anyway, the question is about the compile time messages or lack thereof, not about the unit test result.
Code under test:
using System;
using System.Diagnostics.Contracts;
namespace DomainModel
{
[ContractClass(typeof(IPersonContract))]
public interface IPerson
{
string Name { get; set; }
}
[ContractClassFor(typeof(IPerson))]
public abstract class IPersonContract : IPerson
{
private IPersonContract() { }
string IPerson.Name
{
get
{
throw new NotImplementedException();
}
set
{
Contract.Ensures(!string.IsNullOrEmpty(value));
}
}
}
}
And here is my test:
using Moq;
using NUnit.Framework;
using DomainModel;
namespace Unit
{
/// <summary>
/// A test class for IPerson
/// </summary>
[TestFixture()]
public class IPersonShould
{
#region "Unit Tests"
[Test()]
public void ThrowWhenIPersonIsGivenEmptyName()
{
//set up
IPerson IPerson = this.Person;
string expectedResult = null;
//Dim NameParam1 as String = Nothing
Person.Name = null; // Would expect this line to generate warning or error
//perform test
string actualResult = IPerson.Name;
//compare results
Assert.AreEqual(expectedResult, actualResult);
}
#endregion
#region "Setup and Tear down"
private class MyPerson : IPerson {
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
private MyPerson Person;
/// <summary>
/// This runs only once at the beginning of all tests and is used for all tests in the
/// class.
/// </summary>
[TestFixtureSetUp()]
public void InitialSetup()
{
Person = new MyPerson();
}
/// <summary>
/// This runs only once at the end of all tests and is used for all tests in the class.
/// </summary>
[TestFixtureTearDown()]
public void FinalTearDown()
{
}
/// <summary>
/// This setup function runs before each test method
/// </summary>
[SetUp()]
public void SetupForEachTest()
{
}
/// <summary>
/// This setup function runs after each test method
/// </summary>
[TearDown()]
public void TearDownForEachTest()
{
}
#endregion
}
}
And here are my current settings: