While writing a unit test, I wanted to use Assert.AreSame(..)
against a Nullable<T>
type and I got unexpected results. Then I realized that the below code fails:
int? k = 10;
Assert.IsTrue(ReferenceEquals(k, k));
What is happening here?
Also, how can I make sure my method is returning the very same instance I passed to the mock/stub and not just doing return 10
?
Edit:
I usually do the following to make sure I'm getting consistent results in my unit tests:
//Arrange
var result = new string(new[] {'1', '2', '3'});
mock.SetUp(x => x.Method("something").Returns(result);
//Act here
//Assert
Assert.AreSame(result, instance.ValueAssigned);
If I do return "123"
inside Method(..)
, the above test will fail. I was trying to find a way of doing the same with Nullable.
When nullable reference types are enabled, the C# compiler emits warnings for any uninitialized non-nullable property, as these would contain null. As a result, the following, common way of writing entity types cannot be used:
In terms of null checks, the two should always return the same results. If a non-null reference ever equals null (even when using the Null Object pattern), regardless of whether ReferenceEquals or the == operator was used, it's a very bad thing.
This page introduces EF Core's support for nullable reference types, and describes best practices for working with them. The main documentation on required and optional properties and their interaction with nullable reference types is the Required and Optional Properties page. It is recommended you start out by reading that page first.
This implies, of course, a breaking language change such that reference types with no modifier are non-nullable by default. Switching standard reference declarations (no nullable modifier) to be non-nullable is perhaps the most difficult of all the requirements to reduce nullable idiosyncrasy.
What is happening here?
Both arguments are being boxed, to different objects.
Imagine your code is actually this:
int? k = 10;
object x = k; // Boxing operation 1
object y = k; // Boxing operation 2
Assert.IsTrue(ReferenceEquals(x, y));
Don't forget that nullable value types are still value types - so they get boxed when you convert them to reference type expressions.
Also, how can I make sure my method is returning the very same instance I passed to the mock/stub and not just doing return 10?
For value types, that question simply doesn't make sense. Basically, use Assert.AreSame
for reference types, and Assert.AreEqual
for value types. Note that this is independent of nullability. Assert.AreSame(10, 10)
will fail too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With