Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ReturnsNull calls for nullable value types #692

Merged
merged 1 commit into from
Jul 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions src/NSubstitute/Extensions/ReturnsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ public static ConfiguredCall ReturnsNull<T>(this T value) where T : class =>
public static ConfiguredCall ReturnsNullForAnyArgs<T>(this T value) where T : class =>
value.ReturnsForAnyArgs(default(T));

/// <summary>
/// Set null as returned value for this call.
/// </summary>
public static ConfiguredCall ReturnsNull<T>(this T? value) where T : struct =>
value.Returns(default(T?));

/// <summary>
/// Set null as returned value for this call made with any arguments.
/// </summary>
public static ConfiguredCall ReturnsNullForAnyArgs<T>(this T? value) where T : struct =>
value.ReturnsForAnyArgs(default(T?));

/// <summary>
/// Set null as returned value for this call.
/// </summary>
Expand All @@ -46,5 +58,29 @@ public static ConfiguredCall ReturnsNullForAnyArgs<T>(this Task<T> value) where
/// <returns></returns>
public static ConfiguredCall ReturnsNullForAnyArgs<T>(this ValueTask<T> value) where T : class =>
value.ReturnsForAnyArgs(default(T));

/// <summary>
/// Set null as returned value for this call.
/// </summary>
public static ConfiguredCall ReturnsNull<T>(this Task<T?> value) where T : struct =>
value.Returns(default(T?));

/// <summary>
/// Set null as returned value for this call made with any arguments.
/// </summary>
public static ConfiguredCall ReturnsNullForAnyArgs<T>(this Task<T?> value) where T : struct =>
value.ReturnsForAnyArgs(default(T?));

/// <summary>
/// Set null as returned value for this call.
/// </summary>
public static ConfiguredCall ReturnsNull<T>(this ValueTask<T?> value) where T : struct =>
value.Returns(default(T?));

/// <summary>
/// Set null as returned value for this call made with any arguments.
/// </summary>
public static ConfiguredCall ReturnsNullForAnyArgs<T>(this ValueTask<T?> value) where T : struct =>
value.ReturnsForAnyArgs(default(T?));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public interface ISomething
int MethodWithRefParameter(int arg1, ref int arg2);
int MethodWithMultipleRefParameters(int arg1, ref int arg2, ref int arg3);
int MethodWithOutParameter(int arg1, out int arg2);
int? NullableCount();
int? NullableWithParams(int i, string s);

object this[string key] { get; set; }
System.Threading.Tasks.Task Async();
Expand All @@ -26,12 +28,16 @@ public interface ISomething
System.Threading.Tasks.Task<string> SayAsync(string s);
System.Threading.Tasks.Task<SomeClass> SomeActionAsync();
System.Threading.Tasks.Task<SomeClass> SomeActionWithParamsAsync(int i, string s);
System.Threading.Tasks.Task<int?> NullableCountAsync();
System.Threading.Tasks.Task<int?> NullableWithParamsAsync(int i, string s);

System.Threading.Tasks.ValueTask<int> CountValueTaskAsync();
System.Threading.Tasks.ValueTask<string> EchoValueTaskAsync(int i);
System.Threading.Tasks.ValueTask<int> AnythingValueTaskAsync(object stuff);
System.Threading.Tasks.ValueTask<string> SayValueTaskAsync(string s);
System.Threading.Tasks.ValueTask<SomeClass> SomeActionValueTaskAsync();
System.Threading.Tasks.ValueTask<SomeClass> SomeActionWithParamsValueTaskAsync(int i, string s);
System.Threading.Tasks.ValueTask<int?> NullableCountValueTaskAsync();
System.Threading.Tasks.ValueTask<int?> NullableCountValueTaskWithParamsAsync(int i, string s);
}
}
53 changes: 53 additions & 0 deletions tests/NSubstitute.Acceptance.Specs/ReturningResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,59 @@ public void Return_multiple_ValueTask_async_results_from_funcs()
Assert.That(_something.CountValueTaskAsync().Result, Is.EqualTo(3), "Fourth return");
}

[Test]
public void Returns_null_for_nullable_value_type()
{
_something.NullableCount().ReturnsNull();

Assert.That(_something.NullableCount(), Is.Null);
}

[Test]
public void Returns_null_for_any_args_when_nullable_value_type()
{
_something.NullableWithParams(2, "test").ReturnsNullForAnyArgs();

Assert.That(_something.NullableWithParams(123, "something else"), Is.Null);
}

[Test]
public void Returns_null_for_task_of_null_value_type()
{
_something.NullableCountAsync().ReturnsNull();

Assert.That(_something.NullableCountAsync(), Is.TypeOf<Task<int?>>());
Assert.That(_something.NullableCountAsync().Result, Is.Null);
}

[Test]
public void Returns_null_for_any_args_when_task_of_null_value_type()
{
_something.NullableWithParamsAsync(2, "test").ReturnsNullForAnyArgs();

Assert.That(_something.NullableWithParamsAsync(123, "something else"), Is.TypeOf<Task<int?>>());
Assert.That(_something.NullableWithParamsAsync(123, "something else").Result, Is.Null);
}

[Test]
public void Returns_null_for_TaskValue_for_null_value_type()
{
_something.NullableCountValueTaskAsync().ReturnsNull();

Assert.That(_something.NullableCountValueTaskAsync(), Is.TypeOf<ValueTask<int?>>());
Assert.That(_something.NullableCountValueTaskAsync().Result, Is.Null);
}

[Test]
public void Returns_null_for_any_args_when_TaskValue_is_of_null_value_type()
{
_something.NullableCountValueTaskWithParamsAsync(2, "test").ReturnsNullForAnyArgs();

Assert.That(_something.NullableCountValueTaskWithParamsAsync(123, "something else"),
Is.TypeOf<ValueTask<int?>>());
Assert.That(_something.NullableCountValueTaskWithParamsAsync(123, "something else").Result, Is.Null);
}

[SetUp]
public void SetUp()
{
Expand Down