Skip to content

Added exception extensions for ValueTask without return type #864

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

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
24dc639
Provided test for asynchronous event handlers, here you can see that …
jmartschinke Dec 14, 2023
86a6a8e
fixed behaviour of Raise.Event for asynchronous event handlers
jmartschinke Dec 14, 2023
0c933c1
fixed async handling for when-do
jmartschinke Dec 19, 2023
1941c3d
Ability to mock protected methods with and without return value
Jason31569 Nov 20, 2024
2fc9241
Adopt records for some classes
Romfos Dec 15, 2024
b990b77
Obsolete Arg.Compat
Romfos Dec 15, 2024
1a1f964
Enable nullability for public api
Romfos Dec 15, 2024
9d46068
Update changelogs
Romfos Dec 15, 2024
94b64cb
Disable compat warnings for ArgumentMatchingCompat
Romfos Dec 15, 2024
28bd6b6
Remove unsuable files
Romfos Dec 17, 2024
48f7996
Merge branch 'main' of https://github.com/nsubstitute/NSubstitute
Jason31569 Dec 20, 2024
88998b2
Use NullSubstituteReferenceException on null obj
Jason31569 Dec 20, 2024
18191e2
* Use custom exception on protected method mock errors and additional…
Jason31569 Dec 26, 2024
8db3def
Add failing tests to demonstrate issue
JMolenkamp Jan 29, 2025
b7998a2
Test return type equivalence to allow for matching calls when AnyType…
JMolenkamp Jan 29, 2025
ef71a37
Get element type for ref and out parameter to allow for matching call…
JMolenkamp Jan 29, 2025
58a6290
Added exception extensions for ValueTask without return type
Feb 5, 2025
7f63a73
Update changelog
Romfos Feb 16, 2025
382ccc3
Added workaraund for nullability
Romfos Feb 16, 2025
922e883
Update editorconfig
Romfos Feb 16, 2025
ee11ef0
Merge pull request #845 from Jason31569/main
dtchepak Mar 9, 2025
6c37da9
Merge pull request #856 from Romfos/main
dtchepak Mar 9, 2025
eb43889
Merge branch 'nsubstitute:main' into bugfix/async-event-handlers-retu…
jmartschinke Mar 12, 2025
21bd819
Implemented suggestion to move tests to NSubstitute.Acceptance.Specs
jmartschinke Mar 12, 2025
d24adb5
Merge pull request #808 from jmartschinke/bugfix/async-event-handlers…
dtchepak Mar 16, 2025
fed12c4
Merge pull request #862 from JMolenkamp/fix-generic-any-type-matching
dtchepak Mar 16, 2025
25b1a5f
Feature: allow access to MethodInfo from CallInfo
JMolenkamp Jan 29, 2025
05ed0a7
Merge pull request #855 from JMolenkamp/main
dtchepak Mar 23, 2025
33973a1
Added exception extensions for ValueTask without return type
Feb 5, 2025
a57c17a
Merge branch 'main' of https://github.com/marcselman/NSubstitute
Mar 24, 2025
569c836
Fix formatting
Mar 24, 2025
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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
csharp_style_namespace_declarations = file_scoped:warning
dotnet_style_prefer_collection_expression = true:warning
dotnet_style_prefer_collection_expression = true:suggestion
dotnet_style_collection_initializer = true:warning
csharp_style_prefer_primary_constructors = true:warning

Expand Down
1 change: 1 addition & 0 deletions BreakingChanges.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Update target frameworks: .NET 8, .NET Standard 2.0.
* Obsolete api is removed
* CompatArg is marked as obsolete
* Nullability is enabled for public api for .NET 8+. Workaround: you can disable nullability `<Nullable>disable</Nullable>` on project if you don't want to use it. more info https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references

5.0.0 Release
================
Expand Down
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
### 6.x (work in progress)

* [UPDATE] Update target frameworks: .NET8, .NET Standard 2.0
* [UPDATE][BREAKING] Update target frameworks: .NET8, .NET Standard 2.0
* [UPDATE] Drop EOL .NET 6/7 platforms from testing matrix
* [UPDATE] Update github actions steps versions
* [UPDATE] Remove legacy obsolete API
* [UPDATE] Mark as obsolete api CompatArg with pre c# 7.0 support
* [UPDATE][BREAKING] Remove legacy obsolete API
* [UPDATE][BREAKING] Mark as obsolete api CompatArg with pre c# 7.0 support
* [NEW] Added .NET 9 to test matrix
* [UPDATE] Migrate documentation to docfx platform. https://github.com/dotnet/docfx
* [UPDATE][BREAKING] Nullability is enabled for public api for .NET Core TFMs

### 5.3.0 (October 2024)

Expand Down
5 changes: 0 additions & 5 deletions Gemfile

This file was deleted.

81 changes: 0 additions & 81 deletions Gemfile.lock

This file was deleted.

113 changes: 6 additions & 107 deletions src/NSubstitute/Arg.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
using System.Linq.Expressions;
using NSubstitute.Core.Arguments;

// Disable nullability for client API, so it does not affect clients.
#nullable disable annotations
#pragma warning disable CS0419
using System.Linq.Expressions;

namespace NSubstitute;

/// <summary>
/// Argument matchers used for specifying calls to substitutes.
/// </summary>
public static class Arg
public static partial class Arg
{
/// <summary>
/// This type can be used with any matcher to match a generic type parameter.
Expand Down Expand Up @@ -43,7 +39,7 @@ public static ref T Is<T>(T value)
/// Match argument that satisfies <paramref name="predicate"/>.
/// If the <paramref name="predicate"/> throws an exception for an argument it will be treated as non-matching.
/// </summary>
public static ref T Is<T>(Expression<Predicate<T>> predicate)
public static ref T Is<T>(Expression<Predicate<T?>> predicate)
{
return ref ArgumentMatcher.Enqueue<T>(new ExpressionArgumentMatcher<T>(predicate));
}
Expand All @@ -52,7 +48,7 @@ public static ref T Is<T>(Expression<Predicate<T>> predicate)
/// Match argument that satisfies <paramref name="predicate"/>.
/// If the <paramref name="predicate"/> throws an exception for an argument it will be treated as non-matching.
/// </summary>
public static ref T Is<T>(Expression<Predicate<object>> predicate) where T : AnyType
public static ref T Is<T>(Expression<Predicate<object?>> predicate) where T : AnyType
{
return ref ArgumentMatcher.Enqueue<T>(new ExpressionArgumentMatcher<object>(predicate));
}
Expand Down Expand Up @@ -124,105 +120,8 @@ public static ref T Do<T>(Action<object> useArgument) where T : AnyType
return ref ArgumentMatcher.Enqueue<T>(new AnyArgumentMatcher(typeof(AnyType)), x => useArgument(x!));
}

/// <summary>
/// Alternate version of <see cref="Arg"/> matchers for compatibility with pre-C#7 compilers
/// which do not support <c>ref</c> return types. Do not use unless you are unable to use <see cref="Arg"/>.
///
/// For more information see <see href="https://nsubstitute.github.io/help/compat-args">Compatibility Argument
/// Matchers</see> in the NSubstitute documentation.
/// </summary>
public static class Compat
{
/// <summary>
/// Match any argument value compatible with type <typeparamref name="T"/>.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Any{T}" /> instead.
/// </summary>
public static T Any<T>() => Arg.Any<T>();

/// <summary>
/// Match argument that is equal to <paramref name="value"/>.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Is{T}(T)" /> instead.
/// </summary>
public static T Is<T>(T value) => Arg.Is(value);

/// <summary>
/// Match argument that satisfies <paramref name="predicate"/>.
/// If the <paramref name="predicate"/> throws an exception for an argument it will be treated as non-matching.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Is{T}(Expression{Predicate{T}})" /> instead.
/// </summary>
public static T Is<T>(Expression<Predicate<T>> predicate) => Arg.Is(predicate);

/// <summary>
/// Match argument that satisfies <paramref name="predicate"/>.
/// If the <paramref name="predicate"/> throws an exception for an argument it will be treated as non-matching.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Is{T}(Expression{Predicate{T}})" /> instead.
/// </summary>
public static AnyType Is<T>(Expression<Predicate<object>> predicate) where T : AnyType => Arg.Is<T>(predicate);

/// <summary>
/// Invoke any <see cref="Action"/> argument whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke" /> instead.
/// </summary>
public static Action Invoke() => Arg.Invoke();

/// <summary>
/// Invoke any <see cref="Action&lt;T&gt;"/> argument with specified argument whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T}" /> instead.
/// </summary>
public static Action<T> Invoke<T>(T arg) => Arg.Invoke(arg);

/// <summary>
/// Invoke any <see cref="Action&lt;T1,T2&gt;"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T1,T2}" /> instead.
/// </summary>
public static Action<T1, T2> Invoke<T1, T2>(T1 arg1, T2 arg2) => Arg.Invoke(arg1, arg2);

/// <summary>
/// Invoke any <see cref="Action&lt;T1,T2,T3&gt;"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T1,T2,T3}" /> instead.
/// </summary>
public static Action<T1, T2, T3> Invoke<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3) => Arg.Invoke(arg1, arg2, arg3);

/// <summary>
/// Invoke any <see cref="Action&lt;T1,T2,T3,T4&gt;"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T1,T2,T3,T4}" /> instead.
/// </summary>
public static Action<T1, T2, T3, T4> Invoke<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4) => Arg.Invoke(arg1, arg2, arg3, arg4);

/// <summary>
/// Invoke any <typeparamref name="TDelegate"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.InvokeDelegate{TDelegate}" /> instead.
/// </summary>
/// <param name="arguments">Arguments to pass to delegate.</param>
public static TDelegate InvokeDelegate<TDelegate>(params object[] arguments) => Arg.InvokeDelegate<TDelegate>(arguments);

/// <summary>
/// Capture any argument compatible with type <typeparamref name="T"/> and use it to call the <paramref name="useArgument"/> function
/// whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Do{T}" /> instead.
/// </summary>
public static T Do<T>(Action<T> useArgument) => Arg.Do<T>(useArgument);

/// <summary>
/// Capture any argument compatible with type <typeparamref name="T"/> and use it to call the <paramref name="useArgument"/> function
/// whenever a matching call is made to the substitute.
/// </summary>
public static AnyType Do<T>(Action<object> useArgument) where T : AnyType => Arg.Do<T>(useArgument);
}

private static Action<object> InvokeDelegateAction(params object[] arguments)
private static Action<object?> InvokeDelegateAction(params object?[] arguments)
{
return x => ((Delegate)x).DynamicInvoke(arguments);
return x => ((Delegate)x!).DynamicInvoke(arguments);
}
}
3 changes: 0 additions & 3 deletions src/NSubstitute/Callback.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
using NSubstitute.Core;
using System.Collections.Concurrent;

// Disable nullability for client API, so it does not affect clients.
#nullable disable annotations

namespace NSubstitute;

/// <summary>
Expand Down
3 changes: 0 additions & 3 deletions src/NSubstitute/Callbacks/ConfiguredCallback.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using NSubstitute.Core;

// Disable nullability for client API, so it does not affect clients.
#nullable disable annotations

namespace NSubstitute.Callbacks;

public class ConfiguredCallback : EndCallbackChain
Expand Down
108 changes: 108 additions & 0 deletions src/NSubstitute/Compatibility/Arg.Compat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System.Linq.Expressions;

// Disable nullability for client API, so it does not affect clients.
#nullable disable annotations
#pragma warning disable CS0419

namespace NSubstitute;

public static partial class Arg
{
/// <summary>
/// Alternate version of <see cref="Arg"/> matchers for compatibility with pre-C#7 compilers
/// which do not support <c>ref</c> return types. Do not use unless you are unable to use <see cref="Arg"/>.
///
/// For more information see <see href="https://nsubstitute.github.io/help/compat-args">Compatibility Argument
/// Matchers</see> in the NSubstitute documentation.
/// </summary>
[Obsolete("This api is deprecated and will be removed in future versions of product.")]
public static class Compat
{
/// <summary>
/// Match any argument value compatible with type <typeparamref name="T"/>.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Any{T}" /> instead.
/// </summary>
public static T Any<T>() => Arg.Any<T>();

/// <summary>
/// Match argument that is equal to <paramref name="value"/>.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Is{T}(T)" /> instead.
/// </summary>
public static T Is<T>(T value) => Arg.Is(value);

/// <summary>
/// Match argument that satisfies <paramref name="predicate"/>.
/// If the <paramref name="predicate"/> throws an exception for an argument it will be treated as non-matching.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Is{T}(Expression{Predicate{T}})" /> instead.
/// </summary>
public static T Is<T>(Expression<Predicate<T>> predicate) => Arg.Is(predicate);

/// <summary>
/// Match argument that satisfies <paramref name="predicate"/>.
/// If the <paramref name="predicate"/> throws an exception for an argument it will be treated as non-matching.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Is{T}(Expression{Predicate{T}})" /> instead.
/// </summary>
public static AnyType Is<T>(Expression<Predicate<object>> predicate) where T : AnyType => Arg.Is<T>(predicate);

/// <summary>
/// Invoke any <see cref="Action"/> argument whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke" /> instead.
/// </summary>
public static Action Invoke() => Arg.Invoke();

/// <summary>
/// Invoke any <see cref="Action&lt;T&gt;"/> argument with specified argument whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T}" /> instead.
/// </summary>
public static Action<T> Invoke<T>(T arg) => Arg.Invoke(arg);

/// <summary>
/// Invoke any <see cref="Action&lt;T1,T2&gt;"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T1,T2}" /> instead.
/// </summary>
public static Action<T1, T2> Invoke<T1, T2>(T1 arg1, T2 arg2) => Arg.Invoke(arg1, arg2);

/// <summary>
/// Invoke any <see cref="Action&lt;T1,T2,T3&gt;"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T1,T2,T3}" /> instead.
/// </summary>
public static Action<T1, T2, T3> Invoke<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3) => Arg.Invoke(arg1, arg2, arg3);

/// <summary>
/// Invoke any <see cref="Action&lt;T1,T2,T3,T4&gt;"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Invoke{T1,T2,T3,T4}" /> instead.
/// </summary>
public static Action<T1, T2, T3, T4> Invoke<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4) => Arg.Invoke(arg1, arg2, arg3, arg4);

/// <summary>
/// Invoke any <typeparamref name="TDelegate"/> argument with specified arguments whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.InvokeDelegate{TDelegate}" /> instead.
/// </summary>
/// <param name="arguments">Arguments to pass to delegate.</param>
public static TDelegate InvokeDelegate<TDelegate>(params object[] arguments) => Arg.InvokeDelegate<TDelegate>(arguments);

/// <summary>
/// Capture any argument compatible with type <typeparamref name="T"/> and use it to call the <paramref name="useArgument"/> function
/// whenever a matching call is made to the substitute.
/// This is provided for compatibility with older compilers --
/// if possible use <see cref="Arg.Do{T}" /> instead.
/// </summary>
public static T Do<T>(Action<T> useArgument) => Arg.Do<T>(useArgument);

/// <summary>
/// Capture any argument compatible with type <typeparamref name="T"/> and use it to call the <paramref name="useArgument"/> function
/// whenever a matching call is made to the substitute.
/// </summary>
public static AnyType Do<T>(Action<object> useArgument) where T : AnyType => Arg.Do<T>(useArgument);
}
}
Loading
Loading