Skip to content

Commit

Permalink
Add ThrowsAsync for non-generic ValueTask (#1235)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnthcall committed Jan 3, 2023
1 parent 5b560f8 commit 047de59
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The format is loosely based on [Keep a Changelog](http://keepachangelog.com/en/1

* `Mock<T>.RaiseAsync` method for raising "async" events, i.e. events that use a `Func<..., Task>` or `Func<..., ValueTask>` delegate. (@stakx, #1313)
* `setup.Verifiable(Times times, [string failMessage])` method to specify the expected number of calls upfront. `mock.Verify[All]` can then be used to check whether the setup was called that many times. The upper bound (maximum allowed number of calls) will be checked right away, i.e. whenever a setup gets called. (@stakx, #1319)
* Add `ThrowsAsync` methods for non-generic `ValueTask` (@johnthcall, #1235)

## 4.18.4 (2022-12-30)

Expand Down
16 changes: 16 additions & 0 deletions src/Moq/ReturnsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,22 @@ public static partial class ReturnsExtensions
return tcs.Task;
});
}

/// <summary>
/// Specifies the exception to throw when the asynchronous method is invoked.
/// </summary>
/// <typeparam name="TMock">Mocked type.</typeparam>
/// <param name="mock">Returns verb which represents the mocked type and the valuetask return type</param>
/// <param name="exception">Exception instance to throw.</param>
public static IReturnsResult<TMock> ThrowsAsync<TMock>(this IReturns<TMock, ValueTask> mock, Exception exception) where TMock : class
{
return mock.Returns(() =>
{
var tcs = new TaskCompletionSource<bool>();
tcs.SetException(exception);
return new ValueTask(tcs.Task);
});
}

/// <summary>
/// Specifies the exception to throw when the asynchronous method is invoked.
Expand Down
16 changes: 16 additions & 0 deletions tests/Moq.Tests/ReturnsExtensionsFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public interface IAsyncInterface

public interface IValueTaskAsyncInterface
{
ValueTask NoParametersNonGenericValueTaskReturnType();

ValueTask<string> NoParametersRefReturnType();

ValueTask<int> NoParametersValueReturnType();
Expand Down Expand Up @@ -674,6 +676,20 @@ public void ValueTaskReturnsAsyncFunc_onEachInvocation_RefReturnTypeLazyEvaluati
Assert.NotSame(firstTask.Result, secondTask.Result);
}

[Fact]
public void ValueTaskThrowsAsync_on_NoParametersNonGenericValueTaskReturnType()
{
var mock = new Mock<IValueTaskAsyncInterface>();
var exception = new InvalidOperationException();
mock.Setup(x => x.NoParametersNonGenericValueTaskReturnType()).ThrowsAsync(exception);

var task = mock.Object.NoParametersNonGenericValueTaskReturnType();

Assert.IsType<ValueTask>(task);
Assert.True(task.IsFaulted);
Assert.Equal(exception, task.AsTask().Exception.InnerException);
}

[Fact]
public void ValueTaskThrowsAsync_on_NoParametersRefReturnType()
{
Expand Down

0 comments on commit 047de59

Please sign in to comment.