0

I'm trying to write test checking if JSON converter corectly deserialize input to my custom list

    [TestMethod]
    public void JSONInput_Changed()
    {
        List<PointOnChart> _expectedPointsOnChart;
        _expectedPointsOnChart = new List<PointOnChart>();
        _expectedPointsOnChart.Add(new PointOnChart { Timestamp = "2020-02-14T09:00:00.000Z", Value1 = 10, Value2 = 20, Value3 = 30 });
        _expectedPointsOnChart.Add(new PointOnChart { Timestamp = "2020-02-14T09:01:00.000Z", Value1 = 11, Value2 = 21, Value3 = 31 });
        _expectedPointsOnChart.Add(new PointOnChart { Timestamp = "2020-02-14T09:02:00.000Z", Value1 = 12, Value2 = 22, Value3 = 32 });
        _expectedPointsOnChart.Add(new PointOnChart { Timestamp = "2020-02-14T09:03:00.000Z", Value1 = 13, Value2 = 23, Value3 = 33 });

        MultipleBarChart multipleBarChartTest = new MultipleBarChart();
        multipleBarChartTest.MeInitialize(DateTimeIntervalType.Minutes);
        string JSONstring = System.IO.File.ReadAllText(@"C:\Users\slawomirk\source\repos\VIXCharts\iFixMultipleBarChartTests\TestJson.txt");
        multipleBarChartTest.JSONInput = JSONstring;
        List<PointOnChart> resultPointsOnChart = multipleBarChartTest.PointsOnChart;

        //bool areEqual = _expectedPointsOnChart.SequenceEqual(resultPointsOnChart);
        IEnumerable<PointOnChart> resultList;
        resultList = _expectedPointsOnChart.Except(resultPointsOnChart);
        if (resultList.Any())
        {
            Assert.Fail();
        }
    }

List contains object of this class

public class PointOnChart
{
    public string Timestamp { get; set; }
    public double Value1 { get; set; }
    public double Value2 { get; set; }
    public double Value3 { get; set; }
}

And this is file I'm reading to deserialize:

[{"Timestamp":"2020-02-14T09:00:00.000Z","Value1":10,"Value2":20,"Value3":30}, {"Timestamp":"2020-02-14T09:01:00.000Z","Value1":11,"Value2":21,"Value3":31}, {"Timestamp":"2020-02-14T09:02:00.000Z","Value1":12,"Value2":22,"Value3":32}, {"Timestamp":"2020-02-14T09:03:00.000Z","Value1":13,"Value2":23,"Value3":33}]

I tried numerous ways to compare two Lists but all of them fails eg.: - Fluent Assertion - CollectionAssert

When I inspect both List in debug they are identical. I know it's probably trivial but I could find any solution online, thanks in advance.

2
  • Have you tried the SequenceEquals overload that uses a custom IEqualityComparer? Since you haven't defined a way in PointOnChart itself to determine equality, the test framework won't be able to tell if two are the same or not. Commented Feb 19, 2020 at 11:08
  • How does PointOnChart look like? Commented Feb 19, 2020 at 11:09

3 Answers 3

1

You should implement the Equals method for the PointOnChart class, something like this:

public override bool Equals(object other)
{
    if (object.ReferenceEquals(other, this)) return true;

    var obj = other as PointOnChart;

    if (obj == null) return false;

    return this.Timestamp == obj.Timestamp && this.Value1 == obj.Value1 && this.Value2 == obj.Value2 && this.Value3 == obj.Value3;
}

This way the SequenceEquals extension method will operate properly.

Sign up to request clarification or add additional context in comments.

4 Comments

You forgot about GetHashCode()
SequenceEquals will only use the Equals method, although, for completeness, yes, we should also implement GetHashCode.
You should really implement these methods in its own IEqualityComparer<PointOnChart> class. Otherwise you could get into awkward problems, especially if you start to derive from this class and others start to call your Equals() and GetHashCode() methods (like Dictionary<,> or LINQ methods like Distinct(), Join(), etc.).
Don't agree, I think the class should know how to compare itself, this is useful in lots of situations.
0

Instead of polluting your production code with Equals overrides, considering using www.fluentassertions.com and write that statement as:

resultPointsOnChart.Should().BeEquivalentTo(expectedPointsOnChart);

7 Comments

Totally disagree. I think the class should know how to compare itself, it is useful in lots of places.
Highly depends on whether that class is supposed to have value semantics or not. If it doesn't (because it's an entity in a domain), then adding Equals is going to screw things up. NHibernate for instance will suddenly behave differently when the object that you persist overrides Equals. This is orthogonal to what you want in unit tests.
"screw things up"? Do you know what you are saying? This is actually required for NHibernate!
Well, 25 years for me, and few books written on that... but as I said, nevermind.
|
0

In addition to the other answers, i suggest implementing IEquatable<T> as well as overriding GetHashCode() and Equals(Object) like this.

public class PointOnChart : IEquatable<PointOnChart> {

    public string Timestamp { get; set; }
    public double Value1 { get; set; }
    public double Value2 { get; set; }
    public double Value3 { get; set; }

    public override Int32 GetHashCode() => Timestamp.GetHashCode() ^ Value1.GetHashCode() ^ Value2.GetHashCode() ^ Value3.GetHashCode();

    public override Boolean Equals(Object obj) => Equals(obj as PointOnChart);

    public Boolean Equals(PointOnChart other) => other != null && other.Timestamp == Timestamp && other.Value1.Equals(Value1) && other.Value2.Equals(Value2) && other.Value3.Equals(Value3);

}

That'll give you all the comparing you'll need. Will also make it easier to implement an IEqualityComparer or IEqualityComparer<T> if you need it later on.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.