Piotr Falkowski
Piotr Falkowski

Reputation: 1967

Assert.AreEqual fails for int and ulong but not long and uint

Well, I hope my processor is not burned, because:

    [TestMethod]
    public void tenEqualten()
    {
        Int64 a = 10;
        UInt32 b = 10;
        Assert.AreEqual(a, b);
    }

works just fine, but this:

    [TestMethod]
    public void tenNotEqualten()
    {
        Int32 a = 10;
        UInt64 b = 10;
        Assert.AreEqual(a, b);
    }

fails miserably.

Have you got same results, or is it just me? If yes, any ideas, why? If this is known issue for .Net 4.5 than sorry for spam, but I could not find that as a bug.

edit: I found a duplicate here and an explanation here

Upvotes: 12

Views: 8515

Answers (4)

Scott Chamberlain
Scott Chamberlain

Reputation: 127603

In the first method you are calling Assert.AreEqual<T>(T expected, T actual) where T is of type Int64, this is because UInt32 is implicitly castable to Int64. It is the same effect as if you did

    [TestMethod]
    public void tenEqualten()
    {
        Int64 a = 10;
        UInt32 b = 10;
        Assert.AreEqual(a, (Int64)b);
    }

That is why the first version passes.

In the second version you are calling Assert.AreEqual(object expected, object actual) which fails because they are different types and therefor not "equal".

You could make your first version act like your second version by putting the two numbers inside a object this would let you use the same overload of Assert.

    [TestMethod]
    public void tenEqualten()
    {
        Int64 a = 10;
        UInt32 b = 10;
        object c = a;
        object d = b;
        Assert.AreEqual(c, d);
    }

This method will fail exactly the same way your tenNotEqualten method will fail.

Upvotes: 10

Jeroen Vannevel
Jeroen Vannevel

Reputation: 44448

Look at the widening table.

Integer -> Integer , Long, Decimal, Single, Double
UInteger -> UInteger , Long, ULong, Decimal, Single, Double

How does this relate to your code?

When you compare long (Int64) with uint (UInt32), the uint can fit a long so there's no problem here.

However when you compare int (Int32) with ulong (UInt64) you can see that there is no implicit widening available: they don't fit in eachother.

You can see this more clearly by just looking at the method resolution done by intellisense:

enter image description here

enter image description here

And finally:

object c = (int) 10;
object d = (ulong) 10;
Console.WriteLine (c == d);

will yield false

Upvotes: 9

psaxton
psaxton

Reputation: 1843

Use the System.Convert.ToUInt64 method to force the conversion from Int32:

[TestMethod]
public void tenNotEqualten()
{
  Int32 a = 10;
  UInt64 b = 10;
  Assert.AreEqual(Convert.ToUInt64(a), b);
}

Also, it is good practice when using the generic Assert methods to specify the generic parameter to avoid conversion issues. The following throws a more readable compile time error:

Assert.AreEqual<UInt64>(a, b);

The best overloaded method match for 'Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AreEqual(ulong, ulong)' has some invalid arguments

Argument 1: cannot convert from 'int' to 'ulong'

Upvotes: 1

Magnus
Magnus

Reputation: 46997

UInt32 can be cast to Int64 but UInt64 can not be cast to Int32 as it would not fit. You would get a compilation error on the c == d check in the example below.

Int64 a = 10;
UInt32 b = 10;

Console.WriteLine(a == b);

Int32 c = 10;
UInt64 d = 10;

Console.WriteLine(c == d);

Upvotes: 7

Related Questions