1

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: enter image description here

toddmo
  • 20,682
  • 14
  • 97
  • 107

1 Answers1

0

I think you may be a bit confused about how Code Contracts helps you and other developers, so let me try to help.

There are a couple of ways which Code Contracts tries to help:

  1. Annotating your classes with contracts provides 3rd-party developers who reference your library and who are also using Code Contracts to know whether or not they are using your library correctly.
    • This occurs by virtue of an exception being thrown at runtime for, at minimum, Debug builds. The type of exception depends on the type of contracts you are instrumenting your library with.
  2. For developers on your team, number 1 above is also true. In addition, Code Contracts can provide your team static analysis of the contracts you instrument your code with.
    • Static analysis are the warnings and information/event items that appear after you compile projects that have static analysis enabled.

As you know, you can enable Code Contracts to perform static analysis (i.e. "compile-time") and run-time contract checking on a per project basis.

It appears that you have enabled both Perform Runtime Contract Checking and Perform Static Contract Checking on your DomainModel project. The Perform Static Contract Checking will allow the compiler to inform you and your team of potential problems with contracts after performing a build.

The real issue, though, is that you have defined Person in your unit test project. Did you Enable Perform Static Contract Checking in your unit test project? If not, because Person is defined there, no static analysis will occur on the unit test project unless you enable it.

Also, since you are defining Person in the unit test project, you also need to Enable Perform Runtime Contract Checking for Debug builds for the unit test project, too. This is not desirable because it will cause unit tests to take much longer to compile. I know you intend to ultimately move the implementation, as you were just trying to gain understanding about the code you have heretofore written.

But, as an aside, if you should need to use any sort of test-doubles (such as spies), you can mitigate the need to enable this option on your unit test project by defining a separate assembly containing the test-doubles your unit tests require and enabling code contracts on this test-doubles assembly.

fourpastmidnight
  • 4,032
  • 1
  • 35
  • 48
  • I no longer have the project. I can't go try it and see if this answer fixes the problem. Could you set up a project using my code and take a screen shot of the compiler warning given after your answer is applied? I'm so sorry to ask you to do that. – toddmo Mar 03 '16 at 19:22