Independently of any unit testing framework, you can always drop down to the SequenceEquals<object>
overload that also takes a comparer. This will enable you to compare completely disparate lists. This test demonstrates how you can 'trick' .NET into 'thinking' that two heterogeneous arrays are identical:
[Fact]
public void TestDisparateSequences()
{
var ints = new[] { 1, 3, 5, 7 };
var strings = new[] { "foo", "bar", "baz", "qux" };
Assert.True(
ints.Cast<object>().SequenceEqual(
strings.Cast<object>(),
new TrueComparer<object>()),
"Arrays look like they are equal.");
}
private class TrueComparer<T> : IEqualityComparer<T>
{
public bool Equals(T x, T y)
{
return true;
}
public int GetHashCode(T obj)
{
return 0;
}
}
This test passes, because TrueComparer
always returns true.
Obviously, that's not particularly practical, but it points out the relevant building blocks one can use to compare heterogeneous sequences.
SemantiComparison provides a SemanticComparer<T>
class that implements IEqualityComparer<T>
, but it only works on values of the same type. Thus, in order to use it to compare heterogeneous sequences, you'll need to map one of the lists into a sequence of the other type.
Often, you'll already have such a map lying around, but if not, it's a good motivation for building one. Otherwise, you can use use a semantic mapper like AutoMapper.
Assume, as an example, that you have a Foo
class like this:
public class Foo
{
public int Number { get; set; }
public string Text { get; set; }
}
and another Bar
class, very similar:
public class Bar
{
public int Number { get; set; }
public string Text { get; set; }
}
You can now compare foos and bars using a map and SemanticComparison<Bar>
:
[Fact]
public void TestEquivalentSequences()
{
var foos = new[]
{
new Foo { Number = 42, Text = "ploeh" },
new Foo { Number = 1337, Text = "fnaah" }
};
var bars = new[]
{
new Bar { Number = 42, Text = "ploeh" },
new Bar { Number = 1337, Text = "fnaah" }
};
AutoMapper.Mapper.CreateMap<Foo, Bar>();
Assert.True(
foos.Select(AutoMapper.Mapper.Map<Bar>).SequenceEqual(
bars,
new SemanticComparer<Bar>()),
"Mapped arrays should be equivalent.");
}
Still, it will make your life a whole lot easier if you give your objects Structural Equality. This answer only sketches out what's possible, not what's recommended.