SarangK
SarangK

Reputation: 690

Mock a method twice with NSubstitute to first throw error and later return value for the same called signature request

I wanted to mock a method twice with NSubstitute to first throw error and later return value for the same called signature request.

public interface IMyAction
{
    public Task<MyDto> Upsert(CreateRequest requestDto);
}

public class MyAction : IMyAction
{

    private readonly IMyRepository _repository;
    
    public MyAction(IMyRepository repository)
    {
        _repository = repository;
    }
    
    public Task<MyDto> Upsert(CreateRequest requestDto){
    {
        var domainEntity = await _repository.Get(requestDto.Param1);
        if(domainEntity == null)
        {
            try
            {
                // try to create entity
            }
            catch(RecordExistsException) // Throws when another concurrent request creates the same entity. Need to test this catch block scenario
            {
                domainEntity = await _repository.Get(requestDto.Param1);
                // 
                //...perform update operation using the domainEntity and requestDto
                //
            }
            catch(Exception ex)
            {
                throw
            }
        }
    }
}

I have an edge case where I want the first call should throw an exception and the second call should return dto. Both calls have the same value for the parameter.

I am using NSubstitute to mock the dependencies in xunit test.

My setup:

IMyRepository _repository = Substitute.For<IMyRepository>();
var myAction = new MyAction(_repository);

_repository.Get(Arg.Any<string>()).Throws<NotFoundException>();
_repository.When(x => x.Get(Arg.Is<string>(r => r == "id1")))
           .Do(x => _repository.Get(Arg.Is<string>(r => r == "id1")).Returns(new MyDto()));

Expectation:

_repository.Get("id1").Throws<NotFoundException>(); // first call invocation
_repository.Get("id1").Returns(new MyDto()); // second call invocation

but when myAction.Upsert(new CreateRequest()); called the domainEntity gets returned in the first call rather throwing exception.

Upvotes: 4

Views: 4690

Answers (1)

SarangK
SarangK

Reputation: 690

After digging deep into SO, I found one solution here.

For my case, I fixed the issue by mocking as below-

_repository.Get("id1").Returns(x => throw new NotFoundException(), x => new MyDto());

Returns() also supports passing multiple functions to return from, which allows one call in a sequence to throw an exception or perform some other action.

Upvotes: 14

Related Questions