crhodes
crhodes

Reputation: 45

C# ASP.Net MVC - Unit Test Assert Method Fail

So a quick rundown about the program I am testing. The program is a small app that register athletes' track records from all kinds of track meet. Right now I am testing the functionality of the option to create a new meet "CreateMeet". Every meet have different type of events: track, javelin, etc... and it takes place at specific time and location.

I wrote a small test function that allows me to test the creation of a new meet into the database, and so far the test failed because according to the test results, the problem is in my Assert function. I was sure that it would work but I guess it didn't. The test failure error gives me this:

Test Failed - CreateMeet
Message: Assert.IsTrue failed. 

Below is the test function:

public void CreateMeet()
    {
        var createMeet = new Meet()
        {
            MeetId = 1234,
            MeetName = Spring Meet,
            MeetDate = DateTime.Now,
            MeetLocation = "Paris, France",
            MeasurementType = "Metric"
        };

        var MeetController = new MeetsController();

        MeetController.AddMeet(createMeet);

        var testList = new List<Meet>(MeetController.RetrieveAllMeets());

        Assert.IsTrue(testList.Contains(createMeet));

    }

Which Assert or which type of function do you guys think I may need for this function to generate a successful test? I'm stumped on any other options. Your input is appreciated.

UPDATE Additional code as per D-Shih's request.

public IList<Meet> RetrieveAllMeets()
        {
            JObject jsonMeetObj = JObject.Parse(FieldScribeAPIRequests.FieldScribeGETAsync(FieldScribeAPIRequests.FieldScribeAPIRootAddress + "meets"));

            IList<JToken> results = jsonMeetObj["value"].Children().ToList();

            IList<Meet> meets = new List<Meet>();

            foreach (JToken item in results)
                meets.Add(item.ToObject<Meet>());

            return meets;
        }

Upvotes: 0

Views: 240

Answers (3)

Shetty
Shetty

Reputation: 1892

Since you are storing meet with With Id , instead of retrieving all meets and checking if the collection contains the meet, write a method to get meet by meet id. Assert that it returns a meet and all properties that you are expecting do match. Take a look at fluent assertions which can make things simpler for you when it comes to assertions. http://fluentassertions.com/

Also, since you mentioned is as "Unit test" you should consider mocking to create a kind of in-memory collection and test against them instead of testing against Database.

Upvotes: 1

D-Shih
D-Shih

Reputation: 46219

From your question your expect might want to compare object's fields from Meet Class.

Contain method in List which will be to check object exist by Equals method.

This method determines equality by using the default equality comparer, as defined by the object's implementation of the IEquatable.Equals method for T (the type of values in the list).

Meet is a reference type,When you used Contains method will compare object's pointer.

A Simple way to do override Equals(object obj) on Meet

public class Meet
{
    public int MeetId { get; set; }
    public string MeetName { get; set; }
    public DateTime MeetDate { get; set; }
    public string MeetLocation { get; set; }
    public string MeasurementType { get; set; }

    public override bool Equals(object obj)
    {
        Meet input = obj as Meet;

        if (obj==null)
            return false;

        return MeetId == input.MeetId &&
               MeetName == input.MeetName &&
               MeetDate == input.MeetDate &&
               MeetLocation == input.MeetLocation &&
               MeasurementType == input.MeasurementType;
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

Upvotes: 1

user5151179
user5151179

Reputation: 585

I believe you're comparing instances, when you want to compare values.

Briefly, the object 'createMeet' is not the same object as will be found in 'testList' - they are of the same class, and they hold the same data values, but they are not the same instance of an object.

To get it to do what you want, you could build a CompareTo(Meet) method on your DTO that compares all the field values, and returns a true/false that the objects are 'data equivalent'.

-- Edit: further info.

Consider the following class

public class DTO
{
    public int Value;

    public bool CompareTo(DTO Target)
    {
        return (Target.Value == Value);
    }
}

Now, consider this code:

private void button1_Click(object sender, EventArgs e)
{
    DTO a = new DTO();
    DTO b = new DTO();

    a.Value = 1;
    b.Value = 1;

    if (a == b)
        MessageBox.Show("Should not happen");

    if (a.CompareTo(b))
        MessageBox.Show("Should happen");
}

Variables a and b are data equivalent; they mean the same thing. But they are not the same instance of an object. So, the first if statement fails, and you will not see "Should not happen", but the second if passes, and you will see "Should happen".

You could override the == operator like below, but I wouldn't recommend it:

public class DTO
{
    public int Value;

    public bool CompareTo(DTO Target)
    {
        return (Target.Value == Value);
    }

    public static bool operator ==(DTO a, DTO b)
    {
        return (a.Value == b.Value);
    }

    public static bool operator !=(DTO a, DTO b)
    {
        return (a.Value != b.Value);
    }
}

Upvotes: 1

Related Questions