public class Foo
{
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public override int GetHashCode()
{
var hash = 17;
hash *= 23 + x.GetHashCode();
hash *= 23 + y.GetHashCode();
hash *= 23 + z.GetHashCode();
}
}
When you go to Unit Test the GetHashCode, I’m torn between calculating the original components and repeating the function or using a predetermined value:
[TestMethod]
public void Test1
{
var x = 1; y = 2; z = 3;
var foo = new Foo() { X = x, Y = y, Z = z };
var hash = 17;
hash *= 23 + x.GetHashCode();
hash *= 23 + y.GetHashCode();
hash *= 23 + z.GetHashCode();
var expected = hash;
var actual = foo.GetHashCode();
Assert.AreEqual(expected, actual);
}
[TestMethod]
public void Test2
{
var x = 1; y = 2; z = 3;
var foo = new Foo() { X = x, Y = y, Z = z };
var expected = ? //Some predetermined value (calculated by hand?)
var actual = foo.GetHashCode();
Assert.AreEqual(expected, actual);
}
Or is there some other way?
Unit testing is for testing logic. Is the
GetHashCodecalculation itself logic? Not really, although opinions may vary.The relevant logic here is that two objects that are equal have the same hash code, i.e.
EqualsandHashCodeare compatible. Or, quoting from the docs:So I would write unit tests that guarantee that those conditions are met, not that the internal implementation of
GetHashCodematches a predetermined procedure.Both of your example tests are highly brittle, and perfectly valid
GetHashCodeimplementations would fail them. Recall that one of the major purposes of unit tests is to allow refactoring without fear. But, nobody can refactorGetHashCodewithout your unit tests breaking.