diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index a8ffcc3c..377f517e 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: os: [windows-latest, ubuntu-latest, macOS-latest] - framework: [net6.0, net7.0, net8.0] + framework: [net8.0] include: - os: windows-latest framework: net462 @@ -18,14 +18,12 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x - 7.0.x 8.0.x - name: Build @@ -38,16 +36,14 @@ jobs: runs-on: windows-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x - 7.0.x 8.0.x # used for documentation @@ -64,10 +60,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x diff --git a/BreakingChanges.md b/BreakingChanges.md index c14c8c48..e1a9094c 100644 --- a/BreakingChanges.md +++ b/BreakingChanges.md @@ -1,3 +1,10 @@ +6.0.0 Release +================ + +* Update target frameworks: .NET 8, .NET Standard 2.0. +* Obsolete api is removed +* CompatArg is marked as obsolete + 5.0.0 Release ================ @@ -91,7 +98,7 @@ Workaround: Use `NSubstitute.Received.InOrder`. Signed v3.x package to fix libraries that work with a mix of NSubstitute verisons. See #324. -3.0.0 Release +3.0.0 Release ================ NOTE: unsigned. Fixed in 3.0.1. @@ -108,7 +115,7 @@ Standard 1.3 compatible target such as .NET 4.6 or later. See compatibility matr https://github.com/dotnet/standard/blob/master/docs/versions.md -1.10.0 Release +1.10.0 Release ================ Substitutes will now automatically return an empty `IQueryable` for @@ -116,7 +123,7 @@ members that return that type. Tests previously relying on a substitute `IQueryable` will no longer work properly. Reason: -- Code that uses an `IQueryable` can now run using the auto-subbed +- Code that uses an `IQueryable` can now run using the auto-subbed value without causing null pointer exceptions (see issue #67). Fix: @@ -128,10 +135,10 @@ to return a real `IQueryable` instead. If a substitute is required, explicitl ``` -1.9.1 Release +1.9.1 Release ================ -Substitutes set up to throw exception for methods with return type Task +Substitutes set up to throw exception for methods with return type Task cause compilation to fail due to the call being ambiguous (CS0121). "The call is ambiguous between the following methods or properties: `.Returns>` and `.Returns`" @@ -146,7 +153,7 @@ Fix: New: `sub.Method().Returns(x => { throw new Exception() });` -1.8.0 Release +1.8.0 Release ================ Incorrect use of argument matchers outside of a member call, particularly within a @@ -214,7 +221,7 @@ Fix: --------------- -In rare cases the new `Returns()` and `ReturnsForAnyArgs()` overloads can cause compilation to fail due to the call being ambiguous (CS0121). +In rare cases the new `Returns()` and `ReturnsForAnyArgs()` overloads can cause compilation to fail due to the call being ambiguous (CS0121). Reason: - The new overloads allow a sequence of callbacks to be used for return values. A common example is return several values, then throwing an exception. @@ -229,7 +236,7 @@ Fix: Auto-substitute from substitutes of `Func` delegates (following the same rules as auto-subbing for methods and properties). So the delegate returned from `Substitute.For>()` will return a substitute of `IFoo`. This means some substitutes for delegates that used to return null will now return a new substitute. Reason: -- Reduced setup when substituting for `Func` delegates, and consistency with behaviour for properties and methods. +- Reduced setup when substituting for `Func` delegates, and consistency with behaviour for properties and methods. Fix: - Explicitly return null from substitute delegates when required for a test. diff --git a/CHANGELOG.md b/CHANGELOG.md index 50208ad6..03288747 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +### 6.x (work in progress) + +* [UPDATE] 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 + + ### 5.3.0 (October 2024) * [NEW] Introduced `Substitute.ForTypeForwardingTo` to create substitutes that forward interceptable calls to a concrete class. This provides an easy way of implementing a test spy over an existing type. Designed and implemented by @marcoregueira in https://github.com/nsubstitute/NSubstitute/pull/700 from a proposal by @wsaeed. Thanks to all who contributed to discussions of this feature. @@ -40,7 +49,7 @@ Many thanks to @alexandrnikitin, @Romfos, @brad, and @304NotModified for their c ### 4.4.0 (Jul 2022) -* [FIX] Fix issue checking for constructor args on null object. Thanks to @phongphanq, and @appel1! Thanks also to +* [FIX] Fix issue checking for constructor args on null object. Thanks to @phongphanq, and @appel1! Thanks also to @Mandroide for code review. (#683, #685) * [UPDATE] Update to Castle Core v5. Thanks @Havunen! (#690, #673) * [NEW] Add `.ThrowsAsync()` that will correctly mock exception on async methods. Thanks @Socolin! (#609, #663) diff --git a/Directory.Build.props b/Directory.Build.props index 14c7e56f..bed4e829 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,8 +5,6 @@ See more here https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2019 --> - true - true latest enable @@ -15,8 +13,4 @@ $(MSBuildThisFileDirectory)\bin\$(Configuration)\$(MSBuildProjectName)\ - - - - \ No newline at end of file diff --git a/src/NSubstitute/Compatibility/CompatArg.cs b/src/NSubstitute/Compatibility/CompatArg.cs index ad4f6797..0d10b70b 100644 --- a/src/NSubstitute/Compatibility/CompatArg.cs +++ b/src/NSubstitute/Compatibility/CompatArg.cs @@ -17,6 +17,7 @@ namespace NSubstitute.Compatibility; /// For more information see Compatibility Argument /// Matchers in the NSubstitute documentation. /// +[Obsolete("This api is deprecated and will be removed in future versions of product.")] public class CompatArg { private CompatArg() { } diff --git a/src/NSubstitute/Compatibility/DiagnosticsNullabilityAttributes.cs b/src/NSubstitute/Compatibility/DiagnosticsNullabilityAttributes.cs index f717db57..d4419228 100644 --- a/src/NSubstitute/Compatibility/DiagnosticsNullabilityAttributes.cs +++ b/src/NSubstitute/Compatibility/DiagnosticsNullabilityAttributes.cs @@ -1,4 +1,4 @@ -#if !SYSTEM_DIAGNOSTICS_CODEANALYSIS_NULLABILITY +#if NETSTANDARD2_0 // This was copied from https://github.com/dotnet/runtime/blob/39b9607807f29e48cae4652cd74735182b31182e/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/NullableAttributes.cs // and updated to have the scope of the attributes be internal. diff --git a/src/NSubstitute/Core/Argument.cs b/src/NSubstitute/Core/Argument.cs index a2709736..9313a660 100644 --- a/src/NSubstitute/Core/Argument.cs +++ b/src/NSubstitute/Core/Argument.cs @@ -1,47 +1,18 @@ namespace NSubstitute.Core; -public class Argument +public class Argument(ICall call, int argIndex) { - private readonly ICall? _call; - private readonly int _argIndex; - - private readonly Type? _declaredType; - private readonly Func? _getValue; - private readonly Action? _setValue; - - [Obsolete("This constructor overload is deprecated and will be removed in the next version.")] - public Argument(Type declaredType, Func getValue, Action setValue) - { - _declaredType = declaredType; - _getValue = getValue; - _setValue = setValue; - } - - public Argument(ICall call, int argIndex) - { - _call = call; - _argIndex = argIndex; - } + private readonly ICall? _call = call; public object? Value { - get => _getValue != null ? _getValue() : _call!.GetArguments()[_argIndex]; - set - { - if (_setValue != null) - { - _setValue(value); - } - else - { - _call!.GetArguments()[_argIndex] = value; - } - } + get => _call!.GetArguments()[argIndex]; + set => _call!.GetArguments()[argIndex] = value; } public bool IsByRef => DeclaredType.IsByRef; - public Type DeclaredType => _declaredType ?? _call!.GetParameterInfos()[_argIndex].ParameterType; + public Type DeclaredType => _call!.GetParameterInfos()[argIndex].ParameterType; public Type ActualType => Value == null ? DeclaredType : Value.GetType(); diff --git a/src/NSubstitute/Core/ArgumentSpecificationDequeue.cs b/src/NSubstitute/Core/ArgumentSpecificationDequeue.cs index 81e6d481..87d719a0 100644 --- a/src/NSubstitute/Core/ArgumentSpecificationDequeue.cs +++ b/src/NSubstitute/Core/ArgumentSpecificationDequeue.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using NSubstitute.Core.Arguments; +using NSubstitute.Core.Arguments; namespace NSubstitute.Core; @@ -20,9 +19,4 @@ public IList DequeueAllArgumentSpecificationsForMethod(i var queuedArgSpecifications = dequeueAllQueuedArgSpecs.Invoke(); return queuedArgSpecifications; } - - public IList DequeueAllArgumentSpecificationsForMethod(MethodInfo methodInfo) - { - return DequeueAllArgumentSpecificationsForMethod(methodInfo.GetParameters().Length); - } } \ No newline at end of file diff --git a/src/NSubstitute/Core/Call.cs b/src/NSubstitute/Core/Call.cs index affd4f56..9ff95e10 100644 --- a/src/NSubstitute/Core/Call.cs +++ b/src/NSubstitute/Core/Call.cs @@ -1,6 +1,6 @@ -using System.Reflection; using NSubstitute.Core.Arguments; using NSubstitute.Exceptions; +using System.Reflection; namespace NSubstitute.Core; @@ -15,19 +15,8 @@ public class Call : ICall, /* Performance optimization */ CallCollection.IReceiv private long? _sequenceNumber; private readonly Func? _baseMethod; - [Obsolete("This constructor is deprecated and will be removed in future version of product.")] - public Call(MethodInfo methodInfo, - object?[] arguments, - object target, - IList argumentSpecifications, - IParameterInfo[] parameterInfos, - Func baseMethod) - : this(methodInfo, arguments, target, argumentSpecifications, baseMethod) - { - _parameterInfosCached = parameterInfos ?? throw new ArgumentNullException(nameof(parameterInfos)); - } - - public Call(MethodInfo methodInfo, + public Call( + MethodInfo methodInfo, object?[] arguments, object target, IList argumentSpecifications, diff --git a/src/NSubstitute/Core/CallRouter.cs b/src/NSubstitute/Core/CallRouter.cs index 45201a5f..0b2480c5 100644 --- a/src/NSubstitute/Core/CallRouter.cs +++ b/src/NSubstitute/Core/CallRouter.cs @@ -42,9 +42,6 @@ public IEnumerable ReceivedCalls() return substituteState.ReceivedCalls.AllCalls(); } - public void SetRoute(Func getRoute) => - threadContext.SetNextRoute(this, getRoute); - public object? Route(ICall call) { threadContext.SetLastCallRouter(this); diff --git a/src/NSubstitute/Core/CallSpecificationFactoryFactoryYesThatsRight.cs b/src/NSubstitute/Core/CallSpecificationFactoryFactoryYesThatsRight.cs deleted file mode 100644 index abf0f2b2..00000000 --- a/src/NSubstitute/Core/CallSpecificationFactoryFactoryYesThatsRight.cs +++ /dev/null @@ -1,14 +0,0 @@ -using NSubstitute.Core.DependencyInjection; - -namespace NSubstitute.Core; - -public static class CallSpecificationFactoryFactoryYesThatsRight -{ - [Obsolete("This factory is deprecated and will be removed in future versions of the product. " + - "Please use '" + nameof(SubstitutionContext) + "." + nameof(SubstitutionContext.Current) + "." + - nameof(SubstitutionContext.Current.CallSpecificationFactory) + "' instead. " + - "Use " + nameof(NSubstituteDefaultFactory) + " services if you need to activate a new instance.")] - // ReSharper disable once UnusedMember.Global - is left for API compatibility from other libraries. - public static ICallSpecificationFactory CreateCallSpecFactory() => - NSubstituteDefaultFactory.DefaultContainer.Resolve(); -} \ No newline at end of file diff --git a/src/NSubstitute/Core/IArgumentSpecificationDequeue.cs b/src/NSubstitute/Core/IArgumentSpecificationDequeue.cs index c7b7ee66..f468dfba 100644 --- a/src/NSubstitute/Core/IArgumentSpecificationDequeue.cs +++ b/src/NSubstitute/Core/IArgumentSpecificationDequeue.cs @@ -1,12 +1,8 @@ -using System.Reflection; -using NSubstitute.Core.Arguments; +using NSubstitute.Core.Arguments; namespace NSubstitute.Core; public interface IArgumentSpecificationDequeue { - [Obsolete("This method is deprecated and will be removed in future versions of product.")] - IList DequeueAllArgumentSpecificationsForMethod(MethodInfo methodInfo); - IList DequeueAllArgumentSpecificationsForMethod(int parametersCount); } \ No newline at end of file diff --git a/src/NSubstitute/Core/ICallRouter.cs b/src/NSubstitute/Core/ICallRouter.cs index 22aa5e1c..df061f88 100644 --- a/src/NSubstitute/Core/ICallRouter.cs +++ b/src/NSubstitute/Core/ICallRouter.cs @@ -1,5 +1,3 @@ -using NSubstitute.Routing; - namespace NSubstitute.Core; public interface ICallRouter @@ -15,9 +13,6 @@ public interface ICallRouter ConfiguredCall LastCallShouldReturn(IReturn returnValue, MatchArgs matchArgs, PendingSpecificationInfo pendingSpecInfo); object? Route(ICall call); IEnumerable ReceivedCalls(); - [Obsolete("This method is deprecated and will be removed in future versions of the product. " + - "Please use " + nameof(IThreadLocalContext) + "." + nameof(IThreadLocalContext.SetNextRoute) + " method instead.")] - void SetRoute(Func getRoute); void SetReturnForType(Type type, IReturn returnValue); void RegisterCustomCallHandlerFactory(CallHandlerFactory factory); void Clear(ClearOptions clear); diff --git a/src/NSubstitute/Core/ISubstitutionContext.cs b/src/NSubstitute/Core/ISubstitutionContext.cs index de5609d5..fb349c68 100644 --- a/src/NSubstitute/Core/ISubstitutionContext.cs +++ b/src/NSubstitute/Core/ISubstitutionContext.cs @@ -1,4 +1,3 @@ -using NSubstitute.Core.Arguments; using NSubstitute.Routing; namespace NSubstitute.Core; @@ -16,67 +15,4 @@ public interface ISubstitutionContext IThreadLocalContext ThreadContext { get; } ICallRouter GetCallRouterFor(object substitute); - - [Obsolete("This property is obsolete and will be removed in a future version of the product.")] - SequenceNumberGenerator SequenceNumberGenerator { get; } - - [Obsolete("This property is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.PendingSpecification) + " property instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.PendingSpecification) + ".")] - PendingSpecificationInfo? PendingSpecificationInfo { get; set; } - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.LastCallShouldReturn) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.LastCallShouldReturn) + "(...).")] - ConfiguredCall LastCallShouldReturn(IReturn value, MatchArgs matchArgs); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.SetLastCallRouter) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.SetLastCallRouter) + "(...).")] - void LastCallRouter(ICallRouter callRouter); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.EnqueueArgumentSpecification) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.EnqueueArgumentSpecification) + "(...).")] - void EnqueueArgumentSpecification(IArgumentSpecification spec); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.DequeueAllArgumentSpecifications) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.DequeueAllArgumentSpecifications) + "().")] - IList DequeueAllArgumentSpecifications(); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.SetPendingRaisingEventArgumentsFactory) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.SetPendingRaisingEventArgumentsFactory) + "(...).")] - void RaiseEventForNextCall(Func getArguments); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.UsePendingRaisingEventArgumentsFactory) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.UsePendingRaisingEventArgumentsFactory) + "().")] - Func? DequeuePendingRaisingEventArguments(); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.RunInQueryContext) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.RunInQueryContext) + "(...).")] - IQueryResults RunQuery(Action calls); - - [Obsolete("This property is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.IsQuerying) + " property instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.IsQuerying) + ".")] - bool IsQuerying { get; } - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.RegisterInContextQuery) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.RegisterInContextQuery) + "().", - error: true)] - void AddToQuery(object target, ICallSpecification callSpecification); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.ClearLastCallRouter) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.ClearLastCallRouter) + "().")] - void ClearLastCallRouter(); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(RouteFactory) + " property instead.")] - IRouteFactory GetRouteFactory(); } diff --git a/src/NSubstitute/Core/SubstitutionContext.cs b/src/NSubstitute/Core/SubstitutionContext.cs index a3a4f178..09e9bc92 100644 --- a/src/NSubstitute/Core/SubstitutionContext.cs +++ b/src/NSubstitute/Core/SubstitutionContext.cs @@ -1,168 +1,27 @@ -using NSubstitute.Core.Arguments; using NSubstitute.Core.DependencyInjection; using NSubstitute.Routing; namespace NSubstitute.Core; -public class SubstitutionContext : ISubstitutionContext +public class SubstitutionContext( + ISubstituteFactory substituteFactory, + IRouteFactory routeFactory, + ICallSpecificationFactory callSpecificationFactory, + IThreadLocalContext threadLocalContext, + ICallRouterResolver callRouterResolver) : ISubstitutionContext { public static ISubstitutionContext Current { get; set; } - private readonly ICallRouterResolver _callRouterResolver; - public ISubstituteFactory SubstituteFactory { get; } - public IRouteFactory RouteFactory { get; } - public IThreadLocalContext ThreadContext { get; } - public ICallSpecificationFactory CallSpecificationFactory { get; } + public ISubstituteFactory SubstituteFactory { get; } = substituteFactory; + public IRouteFactory RouteFactory { get; } = routeFactory; + public IThreadLocalContext ThreadContext { get; } = threadLocalContext; + public ICallSpecificationFactory CallSpecificationFactory { get; } = callSpecificationFactory; static SubstitutionContext() { Current = NSubstituteDefaultFactory.CreateSubstitutionContext(); } - public SubstitutionContext(ISubstituteFactory substituteFactory, - IRouteFactory routeFactory, - ICallSpecificationFactory callSpecificationFactory, - IThreadLocalContext threadLocalContext, - ICallRouterResolver callRouterResolver, - SequenceNumberGenerator sequenceNumberGenerator) - { - SubstituteFactory = substituteFactory; - RouteFactory = routeFactory; - CallSpecificationFactory = callSpecificationFactory; - ThreadContext = threadLocalContext; - _callRouterResolver = callRouterResolver; - -#pragma warning disable 618 // Obsolete - SequenceNumberGenerator = sequenceNumberGenerator; -#pragma warning restore 618 // Obsolete - } - public ICallRouter GetCallRouterFor(object substitute) => - _callRouterResolver.ResolveFor(substitute); - - - // *********************************************************** - // ********************** OBSOLETE API ********************** - // API below is obsolete and present for the binary compatibility with the previous versions. - // All implementations are relaying to the non-obsolete members. - - [Obsolete("This property is obsolete and will be removed in a future version of the product.")] - public SequenceNumberGenerator SequenceNumberGenerator { get; } - - [Obsolete("This property is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.IsQuerying) + " property instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.IsQuerying) + ".")] - public bool IsQuerying => ThreadContext.IsQuerying; - - [Obsolete("This property is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.PendingSpecification) + " property instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.PendingSpecification) + ".")] - public PendingSpecificationInfo? PendingSpecificationInfo - { - get - { - if (!ThreadContext.PendingSpecification.HasPendingCallSpecInfo()) - return null; - - // This removes the pending specification, so we need to restore it back. - var consumedSpecInfo = ThreadContext.PendingSpecification.UseCallSpecInfo(); - PendingSpecificationInfo = consumedSpecInfo; - - return consumedSpecInfo; - } - set - { - if (value == null) - { - ThreadContext.PendingSpecification.Clear(); - return; - } - - // Emulate the old API. A bit clumsy, however it's here for the backward compatibility only - // and is not expected to be used frequently. - var unwrappedValue = value.Handle( - spec => Tuple.Create(spec, null), - call => Tuple.Create(null, call)); - - if (unwrappedValue.Item1 != null) - { - ThreadContext.PendingSpecification.SetCallSpecification(unwrappedValue.Item1); - } - else - { - ThreadContext.PendingSpecification.SetLastCall(unwrappedValue.Item2!); - } - } - } - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.LastCallShouldReturn) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.LastCallShouldReturn) + "(...).")] - public ConfiguredCall LastCallShouldReturn(IReturn value, MatchArgs matchArgs) => - ThreadContext.LastCallShouldReturn(value, matchArgs); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.ClearLastCallRouter) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.ClearLastCallRouter) + "().")] - public void ClearLastCallRouter() => - ThreadContext.ClearLastCallRouter(); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(RouteFactory) + " property instead.")] - public IRouteFactory GetRouteFactory() => - RouteFactory; - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.SetLastCallRouter) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.SetLastCallRouter) + "(...).")] - public void LastCallRouter(ICallRouter callRouter) => - ThreadContext.SetLastCallRouter(callRouter); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.EnqueueArgumentSpecification) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.EnqueueArgumentSpecification) + "(...).")] - public void EnqueueArgumentSpecification(IArgumentSpecification spec) => - ThreadContext.EnqueueArgumentSpecification(spec); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.DequeueAllArgumentSpecifications) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.DequeueAllArgumentSpecifications) + "().")] - public IList DequeueAllArgumentSpecifications() => - ThreadContext.DequeueAllArgumentSpecifications(); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.SetPendingRaisingEventArgumentsFactory) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.SetPendingRaisingEventArgumentsFactory) + "(...).")] - public void RaiseEventForNextCall(Func getArguments) => - ThreadContext.SetPendingRaisingEventArgumentsFactory(getArguments); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.UsePendingRaisingEventArgumentsFactory) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.UsePendingRaisingEventArgumentsFactory) + "().")] - public Func? DequeuePendingRaisingEventArguments() => - ThreadContext.UsePendingRaisingEventArgumentsFactory(); - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.RegisterInContextQuery) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.RegisterInContextQuery) + "().", - error: true)] - public void AddToQuery(object target, ICallSpecification callSpecification) - { - // We cannot simulate the API anymore as it changed drastically. - // That should be fine, as this method was expected to be called from the NSubstitute core only. - throw new NotSupportedException( - "This API was obsolete and is not supported anymore. " + - "Please use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.RegisterInContextQuery) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.RegisterInContextQuery) + "()."); - } - - [Obsolete("This method is obsolete and will be removed in a future version of the product. " + - "Use the " + nameof(ThreadContext) + "." + nameof(IThreadLocalContext.RunInQueryContext) + "() method instead. " + - "For example: SubstitutionContext.Current.ThreadContext." + nameof(IThreadLocalContext.RunInQueryContext) + "(...).")] - public IQueryResults RunQuery(Action calls) - { - var query = new Query(CallSpecificationFactory); - ThreadContext.RunInQueryContext(calls, query); - return query.Result(); - } + callRouterResolver.ResolveFor(substitute); } diff --git a/src/NSubstitute/NSubstitute.csproj b/src/NSubstitute/NSubstitute.csproj index 39749dde..3df5a5c3 100644 --- a/src/NSubstitute/NSubstitute.csproj +++ b/src/NSubstitute/NSubstitute.csproj @@ -1,7 +1,7 @@  - net6.0;netstandard2.0;net462 + net8.0;netstandard2.0 true true true @@ -13,7 +13,7 @@ NSubstitute is a friendly substitute for .NET mocking libraries. It has a simple, succinct syntax to help developers write clearer tests. NSubstitute is designed for Arrange-Act-Assert (AAA) testing and with Test Driven Development (TDD) in mind. - 5.0.0 + 6.0.0 Anthony Egerton;David Tchepak;Alexandr Nikitin;Oleksandr Povar NSubstitute NSubstitute @@ -25,12 +25,11 @@ git - - $(DefineConstants);SYSTEM_DIAGNOSTICS_CODEANALYSIS_NULLABILITY + enable - + $(NoWarn);CS8632 @@ -49,10 +48,10 @@ - + - + diff --git a/src/NSubstitute/Proxies/DelegateProxy/DelegateProxyFactory.cs b/src/NSubstitute/Proxies/DelegateProxy/DelegateProxyFactory.cs deleted file mode 100644 index 66ee9e4e..00000000 --- a/src/NSubstitute/Proxies/DelegateProxy/DelegateProxyFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using NSubstitute.Core; -using NSubstitute.Proxies.CastleDynamicProxy; - -namespace NSubstitute.Proxies.DelegateProxy; - -[Obsolete("This class is deprecated and will be removed in future versions of the product.")] -public class DelegateProxyFactory(CastleDynamicProxyFactory objectProxyFactory) : IProxyFactory -{ - private readonly CastleDynamicProxyFactory _castleObjectProxyFactory = objectProxyFactory ?? throw new ArgumentNullException(nameof(objectProxyFactory)); - - public object GenerateProxy(ICallRouter callRouter, Type typeToProxy, Type[]? additionalInterfaces, bool isPartial, object?[]? constructorArguments) - { - // Castle factory can now resolve delegate proxies as well. - return _castleObjectProxyFactory.GenerateProxy(callRouter, typeToProxy, additionalInterfaces, isPartial, constructorArguments); - } -} \ No newline at end of file diff --git a/src/NSubstitute/Proxies/DelegateProxy/ProxiedDelegateTypeAttribute.cs b/src/NSubstitute/Proxies/DelegateProxy/ProxiedDelegateTypeAttribute.cs deleted file mode 100644 index 7ea54948..00000000 --- a/src/NSubstitute/Proxies/DelegateProxy/ProxiedDelegateTypeAttribute.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace NSubstitute.Proxies.DelegateProxy; - -[Obsolete("This class is deprecated and will be removed in future versions of the product.")] -[AttributeUsage(AttributeTargets.Method)] -public class ProxiedDelegateTypeAttribute(Type delegateType) : Attribute -{ - public Type DelegateType { get; } = delegateType; -} \ No newline at end of file diff --git a/src/NSubstitute/Proxies/ProxyFactory.cs b/src/NSubstitute/Proxies/ProxyFactory.cs deleted file mode 100644 index c93ee284..00000000 --- a/src/NSubstitute/Proxies/ProxyFactory.cs +++ /dev/null @@ -1,15 +0,0 @@ -using NSubstitute.Core; - -namespace NSubstitute.Proxies; - -[Obsolete("This class is deprecated and will be removed in future versions of the product.")] -public class ProxyFactory(IProxyFactory delegateFactory, IProxyFactory dynamicProxyFactory) : IProxyFactory -{ - public object GenerateProxy(ICallRouter callRouter, Type typeToProxy, Type[]? additionalInterfaces, bool isPartial, object?[]? constructorArguments) - { - var isDelegate = typeToProxy.IsDelegate(); - return isDelegate - ? delegateFactory.GenerateProxy(callRouter, typeToProxy, additionalInterfaces, isPartial, constructorArguments) - : dynamicProxyFactory.GenerateProxy(callRouter, typeToProxy, additionalInterfaces, isPartial, constructorArguments); - } -} \ No newline at end of file diff --git a/tests/NSubstitute.Acceptance.Specs/CompatArgsTests.cs b/tests/NSubstitute.Acceptance.Specs/CompatArgsTests.cs index d3e99dfe..6791dc6b 100644 --- a/tests/NSubstitute.Acceptance.Specs/CompatArgsTests.cs +++ b/tests/NSubstitute.Acceptance.Specs/CompatArgsTests.cs @@ -5,6 +5,7 @@ namespace NSubstitute.Acceptance.Specs; +#pragma warning disable CS0618 // Type or member is obsolete public class CompatArgsTests { @@ -15,6 +16,7 @@ public void CompatAndCompatArgInstanceShouldBeInSync() var flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance; var compatMembers = typeof(Arg.Compat).GetMethods(flags).Select(DescribeMethod).OrderBy(x => x); + var compatInstanceMembers = typeof(CompatArg).GetMethods(flags).Select(DescribeMethod).OrderBy(x => x); diff --git a/tests/NSubstitute.Acceptance.Specs/EventRaising.cs b/tests/NSubstitute.Acceptance.Specs/EventRaising.cs index d4eee84a..4a8707b8 100644 --- a/tests/NSubstitute.Acceptance.Specs/EventRaising.cs +++ b/tests/NSubstitute.Acceptance.Specs/EventRaising.cs @@ -361,7 +361,9 @@ public interface IEventSamples public delegate int FuncDelegateWithArgs(int intArg, string stringArg); public delegate void CustomEventThatDoesNotInheritFromEventHandler(object sender, CustomEventArgs args); public class CustomEventArgs : EventArgs { } +#pragma warning disable CS9113 // Parameter is unread. public class CustomEventArgsWithNoDefaultCtor(string arg) : EventArgs +#pragma warning restore CS9113 // Parameter is unread. { } diff --git a/tests/NSubstitute.Acceptance.Specs/FieldReports/MigratingToCompatArgs.cs b/tests/NSubstitute.Acceptance.Specs/FieldReports/MigratingToCompatArgs.cs index 024996bd..704d2f5b 100644 --- a/tests/NSubstitute.Acceptance.Specs/FieldReports/MigratingToCompatArgs.cs +++ b/tests/NSubstitute.Acceptance.Specs/FieldReports/MigratingToCompatArgs.cs @@ -3,6 +3,7 @@ namespace NSubstitute.Acceptance.Specs.FieldReports; +#pragma warning disable CS0618 // Type or member is obsolete /// /// Can migrate from the old matchers to by putting a diff --git a/tests/NSubstitute.Acceptance.Specs/LegacyApiTests.cs b/tests/NSubstitute.Acceptance.Specs/LegacyApiTests.cs deleted file mode 100644 index 6c1b7c67..00000000 --- a/tests/NSubstitute.Acceptance.Specs/LegacyApiTests.cs +++ /dev/null @@ -1,59 +0,0 @@ -using NSubstitute.Core; -using NUnit.Framework; - -namespace NSubstitute.Acceptance.Specs; - -[Obsolete] -public class LegacyApiTests -{ - [Test] - public void Set_pending_specification_should_be_returned_scenario1() - { - var call = Substitute.For(); - var specificationInfo = PendingSpecificationInfo.FromLastCall(call); - - SubstitutionContext.Current.PendingSpecificationInfo = specificationInfo; - var result = SubstitutionContext.Current.PendingSpecificationInfo; - - var encapsulatedObject = result.Handle(x => x, x => x); - Assert.That(encapsulatedObject, Is.SameAs(call)); - } - - [Test] - public void Set_pending_specification_should_be_returned_scenario2() - { - var callSpec = Substitute.For(); - var specificationInfo = PendingSpecificationInfo.FromCallSpecification(callSpec); - - SubstitutionContext.Current.PendingSpecificationInfo = specificationInfo; - var result = SubstitutionContext.Current.PendingSpecificationInfo; - - var encapsulatedObject = result.Handle(x => x, x => x); - Assert.That(encapsulatedObject, Is.SameAs(callSpec)); - } - - [Test] - public void Set_pending_specification_to_null_should_return_null() - { - SubstitutionContext.Current.PendingSpecificationInfo = null; - - var result = SubstitutionContext.Current.PendingSpecificationInfo; - - Assert.That(result, Is.Null); - } - - [Test] - public void Pending_specification_getter_should_not_remove_value() - { - var call = Substitute.For(); - var specificationInfo = PendingSpecificationInfo.FromLastCall(call); - - SubstitutionContext.Current.PendingSpecificationInfo = specificationInfo; - var result = SubstitutionContext.Current.PendingSpecificationInfo; - result = SubstitutionContext.Current.PendingSpecificationInfo; - result = SubstitutionContext.Current.PendingSpecificationInfo; - - var encapsulatedObject = result.Handle(x => x, x => x); - Assert.That(encapsulatedObject, Is.SameAs(call)); - } -} \ No newline at end of file diff --git a/tests/NSubstitute.Acceptance.Specs/NSubstitute.Acceptance.Specs.csproj b/tests/NSubstitute.Acceptance.Specs/NSubstitute.Acceptance.Specs.csproj index 6cbe3007..af32e4a7 100644 --- a/tests/NSubstitute.Acceptance.Specs/NSubstitute.Acceptance.Specs.csproj +++ b/tests/NSubstitute.Acceptance.Specs/NSubstitute.Acceptance.Specs.csproj @@ -1,17 +1,17 @@  - net8.0;net7.0;net6.0;net462 + net8.0;net462 - - - - + + + + - + diff --git a/tests/NSubstitute.Benchmarks/NSubstitute.Benchmarks.csproj b/tests/NSubstitute.Benchmarks/NSubstitute.Benchmarks.csproj index c5d32130..8ae98c34 100644 --- a/tests/NSubstitute.Benchmarks/NSubstitute.Benchmarks.csproj +++ b/tests/NSubstitute.Benchmarks/NSubstitute.Benchmarks.csproj @@ -1,12 +1,12 @@  - net6.0 + net8.0 Exe - +