NSubstitute icon indicating copy to clipboard operation
NSubstitute copied to clipboard

A When/Do substitution that throws an exception also says the call was never received.

Open ErikPhilips opened this issue 2 years ago • 1 comments

Describe the bug A When/Do substitution that throws an exception also says the call was never received.

To Reproduce DotNetFiddle

using System;
using System.Threading.Tasks;
using FluentValidation;
using NSubstitute;
using NSubstitute.ExceptionExtensions;
using FluentAssertions;
					
public class Program
{
	private IValidator<Entity> _validator;
	
	public static async Task Main()
	{
		var program = new Program();
		await program.Test();
	}
	
	public async Task Test()
	{
		var entity = new Entity();
		_validator = Substitute.For<IValidator<Entity>>();
		_validator.WhenForAnyArgs(x => x.ValidateAndThrowAsync(entity))
			.Throw(new ValidationException(string.Empty));
		
		var testMethod = async () => await CreateAsync(entity);
		
		await testMethod.Should().ThrowAsync<ValidationException>();
		await _validator.Received(1).ValidateAndThrowAsync(entity);
	}
	
	public async Task CreateAsync(Entity entity)
	{
		await _validator.ValidateAndThrowAsync(entity);
	}
	
	public class Entity {}
}

Unhandled exception. NSubstitute.Exceptions.ReceivedCallsException: Expected to receive exactly 1 call matching: ValidateAsync(ValidationContext<Program+Entity>, System.Threading.CancellationToken) Actually received no matching calls. Received 1 non-matching call (non-matching arguments indicated with '*' characters): ValidateAsync(ValidationContext<Program+Entity>, System.Threading.CancellationToken)

Expected behaviour I would expect await _validator.Received(1).ValidateAndThrowAsync(entity) not to throw an exception.

Environment:

  • NSubstitute version: 5.0.0
  • Platform: Window .Net 6.0

ErikPhilips avatar Jul 13 '23 06:07 ErikPhilips

Is ValidateAndThrowAsync an extension method? This can cause issues with mocking. Try adding Analyzers and see if it detects anything. From the exception it is expecting a ValidationContext<Entity>, and I'm not sure how equality is defined for that type. You can also match any cancellation token using Arg.Any<CancellationToken>.

dtchepak avatar Jul 30 '23 05:07 dtchepak

Closing this due to inactivity. Please let us know if this still an issue and please provide the requested info - thanks!

304NotModified avatar Apr 29 '24 12:04 304NotModified