Updated post . To avoid confusion about what I am and what I am not doing, I edited this post radically to include a complete code example that causes this problem. In order for this message to be read in any case, all code is placed below.
Reference Information:
I am writing a free interface for testing (I know that it was done, but half the goal is to find out how it works ...), in which I want to check that myNumber is between 3 and 10 with a line of code, for example
myNumber.ShouldBeLessThan(10).And.ShouldBeGreaterThan(10); myListOfCars.ShouldNotBeNull().And.ShouldBeA<IEnumerable<Car>>();
I think you can see, reading the second line, that it should check. Of course, there are more complex test cases ...
To enable the .And syntax, I introduced a helper type called AndHelper , which is returned by each validation method and has an And property that returns everything that was validated. Therefore .And in the previous example should return myNumber so that I can check another condition as well.
I use Code Contracts, and among other things, I verify that the this argument of some of these extensions is not null. This is causing my problem.
My problem:
When I run a Code check of my code, I get a bunch of warnings that a non-zero requirement, such as ShouldBeA<T> , cannot be checked. I tried to solve this by subclassing AndHelper<T> with two classes, ReferenceAndHelper<T> and StructAndHelper<T> , and ReferenceAndHelper<T> has contracts that should ensure that a non-empty requirement is met. However, this does not work.
Each time I use one of these test extensions, I get two warning messages. The statement that the contract "instance! = Null" cannot be verified, and the other - specify the location. The first points to the line where I use the method (for example, line 2 in the first example), and the second points to the line where the contract is indicated, marked // (1) in my code.
My code is:
Please bear with me that this part of the message is quite long. I donβt know what kind of SO recommendations for posting large code fragments (which is still relevant), but if there is a better way, please enlighten me.
Please note that there is code in this section that does not cause this particular error, but it introduces restrictions on the solution. For example, I should have a type ( AndHelper<T> or a subclass) that does not belong to the class / structure.
A couple of tests:
// This test requires that instance != null, and therefore works // with ReferenceAndHelper<T> public static ReferenceAndHelper<T> ShouldBeA<T>(this object instance, string message = "") where T : class { Contract.Requires<ArgumentNullException>(instance != null); // (1) Contract.Ensures(Contract.Result<ReferenceAndHelper<T>>() != null); Assert.IsInstanceOf<T>(instance, message.AsNullIfWhitespace() ?? string.Format("ShouldBeA<{0}> failed.", typeof(T).Name)); return new ReferenceAndHelper<T>((T)instance); } // This test should work for both class and struct types T, and therefore // cannot decide between StructAndHelper<T> and ReferenceAndHelper<T>. // The base class is used. public static AndHelper<T> ShouldBeGreaterThan<T>(this T actual, T expected, string message = "") where T : IComparable { Contract.Ensures(Contract.Result<AndHelper<T>>() != null); (actual.CompareTo(expected) > 0).ShouldBeTrue(message.AsNullIfEmpty() ?? string.Format("ShouldBeGreaterThan failed. {0} is not greater than {1}", actual.ToString(), expected.ToString())); return new AndHelper<T>(actual); } // This is the test that returns the AndHelper<T> that .And is called on. // It is, as you can see, in all possible ways specified that this will be a // ReferenceAndHelper<T>, which has contracts to ensure that the value is not null. public static ReferenceAndHelper<T> ShouldNotBeNull<T>(this T value, string message = "") where T : class { Contract.Requires<ArgumentNullException>(value != null); Contract.Ensures(Contract.Result<ReferenceAndHelper<T>>() != null); Assert.IsNotNull(value, message.AsNullIfWhitespace() ?? "ShouldNotBeNull failed."); return new ReferenceAndHelper<T>(value); }
AndHelper<T> class AndHelper<T> :
public class AndHelper<T> { protected readonly T val; public AndHelper(T value) { this.val = value; } public virtual T And { get { return this.val; } } }
Two subclasses of ReferenceAndHelper<T> :
public class ReferenceAndHelper<T> : AndHelper<T> where T : class { public ReferenceAndHelper(T value) : base(value) { Contract.Requires(value != null); } public override T And { get { Contract.Ensures(Contract.Result<T>() != null); return val; } } [ContractInvariantMethod] void ValueIsNotNullInvariant() { Contract.Invariant(this.val != null); } }
and StructAndHelper<T> :
public class StructAndHelper<T> : AndHelper<T> where T : struct { public StructAndHelper(T value) : base(value) { } public override T And { get { return this.val; } } }