Home > Blockchain >  How can I mock a method throwing an exception which uses the parameter in the exception message?
How can I mock a method throwing an exception which uses the parameter in the exception message?

Time:11-09

Mocking an interface ISomething with method Task<List<int>> GetIdsAsync(int) I can do the following to use the parameter in generating the return:

mock.Setup(x => x.GetIdsAsync(It.IsAny<int>()))
    .ReturnsAsync((int n) => new List<int>(n));

I can also mock the method throwing an exception:

mock.Setup(x => x.GetIdsAsync(It.IsAny<int>()))
    .ThrowsAsync(new InvalidOperationException());

But I would actually like to throw new InvalidOperationException($"{n} is not valid"); using the input parameter to generate the error message in the exception.

I cannot figure out what the syntax would be for this, assuming of course that it is possible?

I tried:

mock.Setup(x => x.GetIdsAsync(It.IsAny<int>()))
    .ThrowsAsync((int n) => new InvalidOperationException($"{n} is not valid"));

Which seemed reasonable but gives a somewhat complex error

 CS1929 'ISetup<ISomething, Task<List<int>>>' does not contain a
 definition for 'ThrowsAsync' and the best extension method overload
 'SequenceExtensions.ThrowsAsync(ISetupSequentialResult<Task>,
 Exception)' requires a receiver of type 'ISetupSequentialResult<Task>'

CodePudding user response:

As of this answer, there is currently no ThrowsAsync that takes a value function similar to ReturnsAsync. All take Exception as the argument.

A work around would be to create a local variable, capture the input parameter in a callback and use that in the throw.

//...

int n = 0;
mock
    .Setup(_ => _.GetIdsAsync(It.IsAny<int>()))
    .Callback((int arg) => n = arg)
    .ThrowsAsync(new InvalidOperationException($"{n} is not valid"));

//...
  • Related