What's the difference between Assert.AreNotEqual and Assert.AreNotSame?

22,626

Solution 1

Almost all the answers given here are correct, but it's probably worth giving an example:

public static string GetSecondWord(string text)
{
    // Yes, an appalling implementation...
    return text.Split(' ')[1];
}

string expected = "world";
string actual = GetSecondWord("hello world");

// Good: the two strings should be *equal* as they have the same contents
Assert.AreEqual(expected, actual);

// Bad: the two string *references* won't be the same
Assert.AreSame(expected, actual);

AreNotEqual and AreNotSame are just inversions of AreEqual and AreSame of course.

EDIT: A rebuttal to the currently accepted answer...

If you use Assert.AreSame with value types, they are boxed. In other words, it's equivalent to doing:

int firstNumber = 1;
int secondNumber = 1;
object boxedFirstNumber = firstNumber;
object boxedSecondNumber = secondNumber;

// There are overloads for AreEqual for various value types
// (assuming NUnit here)
Assert.AreEqual(firstNumber, secondNumber);

// ... but not for AreSame, as it's not intended for use with value types
Assert.AreSame(boxedFirstNumber, boxedSecondNumber);

Neither firstNumber nor secondNumber has an object value, because int is a value type. The reason the AreSame call will fail is because in .NET, boxing a value creates a new box each time. (In Java it sometimes doesn't - this has caught me out before.)

Basically you should never use AreSame when comparing value types. When you're comparing reference types, use AreSame if you want to check for identical references; use AreEqual to check for equivalence under Equals. EDIT: Note that there are situations where NUnit doesn't just use Equals directly; it has built-in support for collections, where the elements in the collections are tested for equality.

The claim in the answer that:

Using the example above changing the int to string, AreSame and AreEqual will return the same value.

entirely depends on how the variables are initialized. If they use string literals, then yes, interning will take care of that. If, however, you use:

string firstString = 1.ToString();
string secondString = 1.ToString();

then AreSame and AreEqual will almost certainly not return the same value.

As for:

The general rule of thumb is to use AreEqual on value types and AreSame on reference types.

I almost never want to check for reference identity. It's rarely useful to me. I want to check for equivalence which is what AreEqual checks for. (I'm not saying that AreSame shouldn't be there - it's a useful method, just far more rarely than AreEqual.)

Solution 2

Two things can be equal, but different objects. AreNotEqual checks the objects values via the equality test, while AreNotSame checks that they are not the same exact object.

It is obvious why we would want to test that things AreNotEqual (we care about the values being tested); what about AreNotSame? The usefulness of this in testing is found when you have passed references around and want to make sure that after your shuffling is done that two references are still the same object.

In a real world case, we use a lot of caching objects to mitigate round trips to the database. After an object has been handed off to the cache system, our unit tests ensure that in some cases we get back the same object (cache was valid) and in other cases we get back a fresh object (cache was invalidated). Note that AreNotEqual would not necessary suffice in this case. If the object had a new timestamp in the database, yet the data was not "different enough" to fail an equality test, AreNotEqual wouldn't notice that we refreshed the object.

Solution 3

AreNotSame does reference comparison, whereas AreNotEqual does an equality comparison.

Solution 4

Assert.AreNotEqual asserts that two values are not equal to each other.

Assert.AreNotSame asserts that two variables do not point to the same object.

Example 1:

int i = 1;
int j = i;
// The values are equal:
Assert.AreEqual(i, j);
// Two value types do *not* represent the same object:
Assert.AreNotSame(i, j);

Example 2:

string s = "A";
string t = s;
// The values are equal:
Assert.AreEqual(s, t);
// Reference types *can* point to the same object:
Assert.AreSame(s, t);

Solution 5

AreNotSame uses reference equality (object.ReferenceEquals) - i.e. are they the same actual instance of an object; AreNotEqual uses conceptual equality (.Equals) - i.e. are they considered equal.

Share:
22,626
Dan Esparza
Author by

Dan Esparza

As a Software Developer I really like Go / Docker / C# / ASP.NET / MVC / Bootstrap / ReactJS and Flux / yarn / webpack / AppVeyor, CircleCI, RedGate Ants, and that my favorite comic has its own website. As a budding software entrepreneur I like Hacker News, Trello, Stripe, Github, CircleCI, Balsqmiq mockups, Pingdom, CloudFlare, MailGun, DigitalOcean and Amazon EC2. As a cook, I really like the French & Good Eats. As an American, I like College Football and Baseball. As an iPhone & iPad user, I like Reeder, & 1Password. As a lover of the interwebs, I like Pinboard.in, Pocket, Flickr, Yelp, Keepass, and Dropbox As a network and web security hobbyist, I follow Bruce and was illuminated by the Base Rate fallacy. As a geek, I really enjoy learning about quantum physics and I'm amazed by the double slit experiment. Feynman was a rock star in my book.

Updated on July 03, 2020

Comments

  • Dan Esparza
    Dan Esparza almost 4 years

    In C#, what's the difference between

    Assert.AreNotEqual
    

    and

    Assert.AreNotSame
    
  • Ilya Ryzhenkov
    Ilya Ryzhenkov over 15 years
    Shouldn't AreSame be generic method with class constraint?
  • Jon Skeet
    Jon Skeet over 15 years
    It would be now, if NUnit came out not caring about 1.1 support, I'm sure.
  • Daniel Earwicker
    Daniel Earwicker over 15 years
    All this confusion raises the question: why not just have a single Assert method?
  • Jon Skeet
    Jon Skeet over 15 years
    @Earwicker: Because you don't always want to check for the same thing. Yes, there could be Assert(bool) - but that couldn't give as much information when you pass it false as AreEqual etc do.
  • Daniel Earwicker
    Daniel Earwicker over 15 years
    Just a thought but how about Debug.Assert(() => x == y); i.e. pass a lambda of type Func<bool>. Then Assert can accept it as Expression<Func<bool>>, so if it fails it can turn it into a string to include it in the test log.
  • Jon Skeet
    Jon Skeet over 15 years
    It's usually the values which are important, and the expression wouldn't show those.
  • Daniel Earwicker
    Daniel Earwicker over 15 years
  • Daniel Earwicker
    Daniel Earwicker over 15 years
    Yes, I should probably try making it into a wrapper around NUnit and see which nice facilities can be reproduced practically.
  • Alexander Bird
    Alexander Bird almost 13 years
    You say "use AreEqual to check for equivalence under Equals.", but doesn't stackoverflow.com/questions/789818/… demonstrate that AreEquals is not quite the same as calling a .Equals function?