During testing I have several Assert helper functions specific to the project. For example, I have to often check whether two IEnumerables are equivalent (exactly same content by reference, not regarding the order). So have a static class for these. E.g.:
internal static class MyAssert
{
public static void AreEquivalent<T>(IEnumerable<T> enumerable1, IEnumerable<T> enumerable2)
{
bool val = false;
if (enumerable2 == null)
{
val = !enumerable1.Any();
} else {
var list1 = enumerable1.ToList();
var list2 = enumerable2.ToList();
val = (list1.Count == list2.Count && list1.Intersect(list2).Count() == list2.Count());
}
Assert.IsTrue(val);
}
}
Then if I use MyAssert.AreEquivalent(enumer1, enumer2);, and it fails, then the whole stack trace is shown inside the helper function. I would like to miss it, so if a developer comes, and sees the source of assert, he only sees that the MyAssert thing failed, but he does not see where was the problem inside my helper function (he cannot do anything with Assert.IsTrue(val)).
I know that it can be done with Assert.IsTrue(MyCollHelper.AreEquivalent(enumer1, enumer2)), but this is not as readebly as the previous.
I not sure that I understand you correctly. If you or the developer will see which part of your method causes the error than use Assert.Fail(). I didn't test it:
internal static class MyAssert
{
public static void AreEquivalent<T>(IEnumerable<T> enumerable1, IEnumerable<T> enumerable2)
{
bool val = false;
if (enumerable2 == null)
{
val = !enumerable1.Any();
if (val == false)
{
Assert.Fail("enumerable2 is empty, enumerable1 is not");
}
}
else if (enumerable1 == null)
{
val = !enumerable2.Any();
if (val == false)
{
Assert.Fail("enumerable1 is empty, enumerable2 is not");
}
}
else
{
var list1 = enumerable1.ToList();
var list2 = enumerable2.ToList();
if (list1.Count != list2.Count)
{
Assert.Fail("Count result is not the same");
}
if (list1.Intersect(list2).Count() != list2.Count())
{
Assert.Fail("count of Intersect enumerable1 is not the same as enumerable2 count");
}
}
}
}
Unfortunately this is impossible now.
Related
I'm trying to do a simple comparison on two objects, simply to track changes on saving to the database, I have the below code which works perfectly on simple objects.
public static List<Variance> Compare<T>(this T original, T current)
{
var variances = new List<Variance>();
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in properties)
{
var v = new Variance
{
PropertyName = property.Name,
Original = property.GetValue(original),
Current = property.GetValue(current)
};
if (v.Original == null && v.Current == null)
{
continue;
}
if ((v.Original == null && v.Current != null) || (v.Original != null && v.Current == null))
{
variances.Add(v);
continue;
}
if (!v.Original.Equals(v.Current))
{
variances.Add(v);
}
}
return variances;
}
but if T is a list the equals need to be changed to a SequenceEqual and I can't think of a way to convert T to the correct list type to do the SequenceEqual check.
Although it's not impossible to use SequenceEqual here, it'd involve either dynamic like in Jasper Kent's answer, or quite a lot of reflection code, I'll outline what you'll need to do if you were using reflection:
check if both the objects are IEnumerable<T>.
get the Type of both objects, and then get the type parameter T as a Type as well
get the method SequenceEquals from Enumerable as a MethodInfo. This involves using LINQ to find the overload with two parameters.
call MakeGenericMethod with T.
Invoke the MethodInfo
I wouldn't want to read, or write that code... Using dynamic is fine I guess, though some people have different opinions...
So here's a third way: I suggest you write your own SequenceEqual method that takes IEnumerables (the non-generic version):
private static bool SequenceEqual(IEnumerable first, IEnumerable second) {
IEnumerator e1 = first.GetEnumerator();
IEnumerator e2 = second.GetEnumerator();
try {
// adapted from https://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs,63644a881e976b52,references
while (e1.MoveNext())
{
if (!(e2.MoveNext() && e1.Current.Equals(e2.Current))) return false;
}
if (e2.MoveNext()) return false;
return true;
} finally {
if (e1 is IDisposable d1) {
d1.Dispose();
}
if (e2 is IDisposable d2) {
d2.Dispose();
}
}
}
Then you can just check whether the objects are IEnumerable:
if (v.Original is Enumerable e1 &&
v.Current is Enumerable e2 &&
!SequenceEqual(e1, e2))
{
variances.Add(v);
}
I think the solution you want is to use dynamic overloading.
I've cut this solution down from yours to get to the nub of it. The call to SwitchEquals() is the equivalent of your v.Original.Equals(v.Current).
static bool SwitchEquals<T>(IEnumerable<T> listA, IEnumerable<T> listB)
{
Console.WriteLine("Doing Sequential Equals");
return true; // Do your sequential equal here
}
static bool SwitchEquals(object objA, object objB)
{
Console.WriteLine("Doing equals");
return objA.Equals(objB); // This is your original equals
}
static void Compare<T>(T original, T current)
{
// Using dynamic means the decision between the tow SwitchEquals methods is made
// At runtime, when the system knows if we have a collection
if (SwitchEquals ((dynamic)original,(dynamic) current))
Console.WriteLine("Match");
else
Console.WriteLine("No match");
}
static void Main(string[] args)
{
Compare(4,5);
Compare (new int[] { 4, 3 }, new int[] { 4, 4 });
}
Recently I decided to play around with overriding the Equals method. I used mainly the MSDN guideline (the updated one I believe). So my implementation end up like this:
public class EqualityCheck
{
public int Age { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public override bool Equals(object obj)
{
if (null == obj)
{
return false;
}
//If obj is on of the expected type return false
EqualityCheck ec = obj as EqualityCheck;
if (null == ec)
{
return false;
}
//return true if the fields match. This is the place where we can decide what combination should be unique
return (Age == ec.Age) && (Name == ec.Name) && (DateOfBirth == ec.DateOfBirth);
}
public bool Equals(EqualityCheck ec)
{
// If parameter is null return false:
if (ec == null)
{
return false;
}
// Return true if the fields match:
return (Age == ec.Age) && (Name == ec.Name);
}
//How to implement GetHashCode for complex object?
}
And also one child class:
public class EqualityCheckChild : EqualityCheck
{
public int Height { get; set; }
public override bool Equals(System.Object obj)
{
// If parameter cannot be cast to ThreeDPoint return false:
EqualityCheckChild ec1 = obj as EqualityCheckChild;
if (ec1 == null)
{
return false;
}
// Return true if the fields match:
return base.Equals(obj) && Height == ec1.Height;
}
public bool Equals(EqualityCheckChild ec1)
{
// Return true if the fields match:
return base.Equals((EqualityCheck)ec1) && Height == ec1.Height;
}
public static bool operator ==(EqualityCheckChild a, EqualityCheckChild b)
{
if (Equals(a, b))
{
return true;
}
if (a == null || b == null)
{
return false;
}
return a.DateOfBirth == b.DateOfBirth && a.Name == b.Name;
}
public static bool operator !=(EqualityCheckChild a, EqualityCheckChild b)
{
return !(a == b);
}
}
I think this is what MSDN shows as implementation, just with removed casts.
I am using VS2015 and .NET 4.5.2. VS marked the casting as redundant, that's when I look up what's the issue with this. I've read about the possible infinity loop and just out of curiosity I decided to recreate it with the code above. However I can't reproduce it.
Since this is not copy-paste code. At least not literally. I wrote it by hand trying to understand what I am doing so I guess it's possible to have some mismatch with the original code which leads to this. But still my question remains - how to reproduce the problem which is also mentioned in the MSDN article?
Attempt to compare an instance of EqualityCheckChild to null.
EqualityCheckChild foo = new EqualityCheckChild();
Console.WriteLine(foo == null);
This code snippet will cause a StackOverflowException, because in the operator== method, if (a == null || b == null) calls itself.
I am currently trying to learn how to use unit testing, and I have created the actual list of 3 animal objects and the expected list of 3 animal objects. The question is how do I Assert to check the lists are equal? I have tried CollectionAssert.AreEqual and Assert.AreEqual but to no avail. Any help would be appreciated.
The test method:
[TestMethod]
public void createAnimalsTest2()
{
animalHandler animalHandler = new animalHandler();
// arrange
List<Animal> expected = new List<Animal>();
Animal dog = new Dog("",0);
Animal cat = new Cat("",0);
Animal mouse = new Mouse("",0);
expected.Add(dog);
expected.Add(cat);
expected.Add(mouse);
//actual
List<Animal> actual = animalHandler.createAnimals("","","",0,0,0);
//assert
//this is the line that does not evaluate as true
Assert.Equals(expected ,actual);
}
That is correct, as the lists might look the same, they are 2 different objects containing the same data.
In order to compare lists, you should use the CollectionAssert
CollectionAssert.AreEqual(expected, actual);
That should do the trick.
Just incase someone comes across this in the future, the answer was I had to create an Override, IEqualityComparer as described below:
public class MyPersonEqualityComparer : IEqualityComparer<MyPerson>
{
public bool Equals(MyPerson x, MyPerson y)
{
if (object.ReferenceEquals(x, y)) return true;
if (object.ReferenceEquals(x, null)||object.ReferenceEquals(y, null)) return false;
return x.Name == y.Name && x.Age == y.Age;
}
public int GetHashCode(MyPerson obj)
{
if (object.ReferenceEquals(obj, null)) return 0;
int hashCodeName = obj.Name == null ? 0 : obj.Name.GetHashCode();
int hasCodeAge = obj.Age.GetHashCode();
return hashCodeName ^ hasCodeAge;
}
}
I am of the opinion that implementing the IEqualityComparer (Equals() and GetHashCode()) for only testing purpose is a code smell. I would rather use the following assertion method, where you can freely define that on which properties you want to do the assertions:
public static void AssertListEquals<TE, TA>(Action<TE, TA> asserter, IEnumerable<TE> expected, IEnumerable<TA> actual)
{
IList<TA> actualList = actual.ToList();
IList<TE> expectedList = expected.ToList();
Assert.True(
actualList.Count == expectedList.Count,
$"Lists have different sizes. Expected list: {expectedList.Count}, actual list: {actualList.Count}");
for (var i = 0; i < expectedList.Count; i++)
{
try
{
asserter.Invoke(expectedList[i], actualList[i]);
}
catch (Exception e)
{
Assert.True(false, $"Assertion failed because: {e.Message}");
}
}
}
In action it would look like as follows:
public void TestMethod()
{
//Arrange
//...
//Act
//...
//Assert
AssertAnimals(expectedAnimals, actualAnimals);
}
private void AssertAnimals(IEnumerable<Animal> expectedAnimals, IEnumerable<Animal> actualAnimals)
{
ListAsserter.AssertListEquals(
(e,a) => AssertAnimal(e,a),
expectedAnimals,
actualAnimals);
}
private void AssertAnimal(Animal expected, Animal actual)
{
Assert.Equal(expected.Name, actual.Name);
Assert.Equal(expected.Weight, actual.Weight);
//Additional properties to assert...
}
I am using XUnit for the simple Assert.True(...) and Assert.Equals(), but you can use any other unit test library for that. Hope it helps someone! ;)
I modified method AssertListEquals() and used standard Assert.All()
public static void AssertListEquals<TE, TA>(IEnumerable<TE> expected, IEnumerable<TA> actual, Action<TE, TA> asserter)
{
if (expected == null && actual == null) return;
Assert.NotNull(expected);
Assert.NotNull(actual);
Assert.True(
actual.Count() == expected.Count(),
$"Lists have different sizes. Expected list: {expected.Count()}, actual list: {actual.Count()}");
var i = 0;
Assert.All(expected, e =>
{
try
{
asserter(e, actual.Skip(i).First());
}
finally
{
i++;
}
});
}
I want to create an FxRule that applies a method, only if the method gets called from a specific class.
NOTE: I don't want to just apply a rule to a method of a particular class, i want to be able to handle methods calling other methods calling other methods which do the boxing.
I'd like to get FxCop to report problems associated with the method that does the boxing.
Below is the code i have so far:
using System;
using System.Linq;
using Microsoft.FxCop.Sdk;
using System.Collections.Generic;
class CheckUpdatableComponents : BaseIntrospectionRule
{
private string[] MethodsToCheck = new string[] { "BeginDraw", "BeginRun", "Draw", "EndRun", "EndDraw", "Update" };
/// <summary>Gets the base class hooked up.</summary>
public CheckUpdatableComponents()
: base("CheckUpdatableComponents", "FxCopRules.Rules", typeof(CheckUpdatableComponents).Assembly)
{
}
public override ProblemCollection Check(string namespaceName, TypeNodeCollection types)
{
foreach (var type in types.Where(T => IsSubClassOf(T, "Microsoft.Xna.Framework.Game")))
{
foreach (var MethodToCheck in MethodsToCheck)
{
Method RunMethod = type.GetMethod(Identifier.For(MethodToCheck));
if (RunMethod != null)
{
Visit(RunMethod);
}
}
}
return Problems;
}
public override void VisitMethod(Method method)
{
Problems.Add(new Problem(GetResolution(), method, method.ToString())); // This problem only appears for each of the RunMethods, and doesn't seem to be recursing down the tree.
foreach (var Instruction in method.Instructions)
{
if (Instruction.NodeType == NodeType.Box ||
Instruction.NodeType == NodeType.Unbox ||
Instruction.NodeType == NodeType.UnboxAny ||
Instruction.OpCode == OpCode.Box ||
Instruction.OpCode == OpCode.Unbox ||
Instruction.OpCode == OpCode.Unbox_Any)
{
}
}
base.VisitMethod(method);
}
private bool IsSubClassOf(TypeNode type, string typeName)
{
if (type.FullName == typeName)
return true;
if (type.BaseType == null)
return false;
else
return IsSubClassOf(type.BaseType, typeName);
}
}
My issue with the above code, is firstly, that it doesn't appear to be recursing. Secondly, that FxCop reports the problems as being associated with the namespace (probably because i kick off the visit using the Check(namespace....) part.
My problem is that i want FxCop to report a method that has boxing as a problem, but only if it gets called by a particular method, however i have no way of walking up the call tree, i can only visit lower nodes to check for problems with my starting location.
Has anyone done this sort of thing before?
How can i find out what methods call a given method?
EDIT: This doesn't work in the case of virtual method calls where the IL is callvirt. See my question here.
I managed to work it out, by discovering the method CallGraph.CallersFor(). I'm now looking for methods declared with a given attribute, or declared by a class with a given attribute, but the principal is the same.
using System;
using System.Linq;
using Microsoft.FxCop.Sdk;
using System.Collections.Generic;
class CheckUpdatableComponents : BaseIntrospectionRule
{
// private string[] MethodsToCheckNames = new string[] { "BeginDraw", "BeginRun", "Draw", "EndRun", "EndDraw", "Update" };
/// <summary>Gets the base class hooked up.</summary>
public CheckUpdatableComponents()
: base("CheckUpdatableComponents", "FxCopRules.Rules", typeof(CheckUpdatableComponents).Assembly)
{
}
public override ProblemCollection Check(Member member)
{
Method method = member as Method;
if (method != null)
{
if (ShouldCheckMethod(method))
{
foreach (var Instruction in method.Instructions)
{
if (Instruction.NodeType == NodeType.Box ||
Instruction.NodeType == NodeType.Unbox ||
Instruction.NodeType == NodeType.UnboxAny ||
Instruction.OpCode == OpCode.Box ||
Instruction.OpCode == OpCode.Unbox ||
Instruction.OpCode == OpCode.Unbox_Any)
{
Problems.Add(new Problem(GetResolution(), Instruction, Instruction.SourceContext.StartLine.ToString()));
}
}
}
}
return Problems;
}
public bool ShouldCheckMethod(Method method)
{
Queue<Method> MethodsToCheck = new Queue<Method>();
List<Method> MethodsChecked = new List<Method>();
MethodsToCheck.Enqueue(method);
while (MethodsToCheck.Count != 0)
{
Method MethodToCheck = MethodsToCheck.Dequeue();
if (!MethodsChecked.Contains(MethodToCheck) && MethodToCheck != null)
{
/*if (IsSubClassOf(MethodToCheck.DeclaringType, "Microsoft.Xna.Framework.Game") &&
MethodsToCheckNames.Contains(MethodToCheck.Name.Name))
{
return true;
}*/
foreach (var attribute in MethodToCheck.Attributes.Union(MethodToCheck.DeclaringType.Attributes))
{
if (attribute.Type != null &&
attribute.Type.FullName == "GridEngine.Components.Debugging.Attributes.FxCop.PerformanceCriticalAttribute")
{
return true;
}
}
// Add methods up the class tree
MethodsToCheck.Enqueue(MethodToCheck.OverriddenMethod);
MethodsToCheck.Enqueue(MethodToCheck.HiddenMethod);
// Add calling methods
foreach (var CallingMethod in CallGraph.CallersFor(MethodToCheck))
{
MethodsToCheck.Enqueue(CallingMethod);
}
}
MethodsChecked.Add(MethodToCheck);
}
return false;
}
private bool IsSubClassOf(TypeNode type, string typeName)
{
if (type.FullName == typeName)
return true;
if (type.BaseType == null)
return false;
else
return IsSubClassOf(type.BaseType, typeName);
}
}
In my MVC3 project, I use an IUrlProvider interface to wrap the UrlHelper class. In one of my controller actions, I have a call like this:
string url = _urlProvider.Action("ValidateCode", new { code = "spam-and-eggs" });
I want to stub this method call in my unit test, which is in a separate project. The test setup looks something like this:
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<object>.Is.Equal(new { code = "spam-and-eggs" }) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
Unfortunately, Arg<object>.Is.Equal(new { code = "spam-and-eggs" }) doesn't work, because new { code = "spam-and-eggs" } != new { code = "spam-and-eggs" } when the anonymous types are declared in different assemblies.
So, is there an alternative syntax I can use with Rhino Mocks to check for matching field values between anonymous objects across assemblies?
Or should I replace the anonymous object declarations with a class, like this?
public class CodeArg
{
public string code { get; set; }
public override bool Equals(object obj)
{
if(obj == null || GetType() != obj.GetType())
{
return false;
}
return code == ((CodeArg)obj).code;
}
public override int GetHashCode()
{
return code.GetHashCode();
}
}
string url = _urlProvider.Action("ValidateCode",
new CodeArg { code = "spam-and-eggs" });
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<CodeArg>.Is.Equal(new CodeArg { code = "spam-and-eggs" }) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
EDIT
If my unit test was in the same project as my controller, comparing the anonymous objects would work fine. Because they are declared in separate assemblies, they will not be equal, even if they have the same field names and values. Comparing anonymous objects created by methods in different namespaces doesn't seem to be a problem.
SOLUTION
I replaced Arg<object>.Is.Equal() with Arg<object>.Matches() using a custom AbstractConstraint:
IUrlProvider urlProvider = MockRepository.GenerateStub<IUrlProvider>();
urlProvider.Stub(u => u.Action(
Arg<string>.Is.Equal("ValidateCode"),
Arg<object>.Matches(new PropertiesMatchConstraint(new { code = "spam-and-eggs" })) ))
.Return("http://www.mysite.com/validate/spam-and-eggs");
public class PropertiesMatchConstraint : AbstractConstraint
{
private readonly object _equal;
public PropertiesMatchConstraint(object obj)
{
_equal = obj;
}
public override bool Eval(object obj)
{
if (obj == null)
{
return (_equal == null);
}
var equalType = _equal.GetType();
var objType = obj.GetType();
foreach (var property in equalType.GetProperties())
{
var otherProperty = objType.GetProperty(property.Name);
if (otherProperty == null || property.GetValue(_equal, null) != otherProperty.GetValue(obj, null))
{
return false;
}
}
return true;
}
public override string Message
{
get
{
string str = _equal == null ? "null" : _equal.ToString();
return "equal to " + str;
}
}
}
Anonymous types do implement Equals and GetHashCode in a pretty normal way, calling GetHashCode and Equals for each of their submembers.
So this should pass:
Assert.AreEqual(new { code = "spam-and-eggs" },
new { code = "spam-and-eggs" });
In other words, I suspect you're looking for the problem in the wrong place.
Note that you have to specify the properties in exactly the right order - so new { a = 0, b = 1 } will not be equal to new { b = 1, a = 0 }; the two objects will be of different types.
EDIT: The anonymous type instance creation expressions have to be in the same assembly, too. This is no doubt the problem in this case.
If Equals allows you to specify an IEqualityComparer<T>, you could probably build one which is able to compare two anonymous types with the same properties by creating an instance of one type from the properties of an instance of the other, and then comparing that to the original of the same type. Of course if you were using nested anonymous types you'd need to do that recursively, which could get ugly...
As GetValue returns a boxed value, this appears to work correctly.
public class PropertiesMatchConstraint : AbstractConstraint
{
private readonly object _equal;
public PropertiesMatchConstraint(object obj)
{
_equal = obj;
}
public override bool Eval(object obj)
{
if (obj == null)
{
return (_equal == null);
}
var equalType = _equal.GetType();
var objType = obj.GetType();
foreach (var property in equalType.GetProperties())
{
var otherProperty = objType.GetProperty(property.Name);
if (otherProperty == null || !_ValuesMatch(property.GetValue(_equal, null), otherProperty.GetValue(obj, null)))
{
return false;
}
}
return true;
}
//fix for boxed conversions object:Guid != object:Guid when both values are the same guid - must call .Equals()
private bool _ValuesMatch(object value, object otherValue)
{
if (value == otherValue)
return true; //return early
if (value != null)
return value.Equals(otherValue);
return otherValue.Equals(value);
}
public override string Message
{
get
{
string str = _equal == null ? "null" : _equal.ToString();
return "equal to " + str;
}
}
}