pose
pose copied to clipboard
Shim Asynchronous methods
Is there a way to shim asynchronous method?
@ashGHub, I believe shimming asynchronous methods should be the same as normal methods. Have you tried this and did it throw an error?
I tried the following code
public class UnitTest1
{
[Fact]
public void Test1()
{
HttpClient httpClient = new HttpClient();
Shim myClassShim = Shim.Replace(() => httpClient.GetStringAsync(Is.A<string>())).With
(HttpClient @this) => throw new Exception("TEST EXCEPTION"));
PoseContext.Isolate(() =>
{
var url = "DUMMY URL";
Func<Task> action = async () => { await httpClient.GetStringAsync(url); };
action.Should().Throw<Exception>()
.WithMessage("TEST EXCEPTION");
});
}
}
But the test won't pass the the shim setup for GetStringAsync. It is throwing
Message: Pose.Exceptions.InvalidShimSignatureException : Mismatched return types
To reproduce this;
- Create an xUnit test project using .net core 2.1.
- Add a nuget package FluentAssertions.
- Use the above code
FYI:
I tried to replace the shim with
Shim myClassShim = Shim.Replace(() => httpClient.GetStringAsync(Is.A<string>())).With(
(HttpClient @this) => Task.Factory.StartNew(() => throw new Exception("TEST EXCEPTION")));
Still, it is throwing the same exception.
Thanks
Because of how delegates are setup the runtime is interpreting your replacement delegate as void
by default. I suggest you try returning a dummy Task<string>
value.
If you really need to throw an exception, you can try the following:
Task.Factory.StartNew<string>(() => throw new Exception("TEST EXCEPTION"));
I used what you've suggested and this error showed up
Message: Pose.Exceptions.InvalidShimSignatureException : Parameters count do not match
It doesn't work for me either. Imagine a test scenario where you're testing a ViewModel that contains an async command, which in turn executes an async call to a component that you want to shim. For me it gives the following exception:
System.Reflection.TargetInvocationException
HResult=0x80131604
Message=Exception has been thrown by the target of an invocation.
Source=System.Private.CoreLib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at Pose.PoseContext.Isolate(Action entryPoint, Shim[] shims)
Inner Exception 1:
InvalidProgramException: Common Language Runtime detected an invalid program.
Sorry, I am trying to mock static method but I want simulate that this call throws a particular exception.
Hi, I'am new of C# and .NET framework. My solution for static methods is:
[TestMethod]
[ExpectedException(typeof(TimeoutException), "Dummy Time Out Exception")]
public void Test_MockStaticMethod_MethodMocked_AndThrowTimeoutException()
{
Func<string> myFunc = delegate ()
{
throw new TimeoutException();
};
Shim consoleShim = Shim.Replace(() => MyItem.GetStaticSession()).With(myFunc);
try
{
PoseContext.Isolate(() =>
{
MyItem.GetStaticSession();
}, consoleShim);
}
catch (Exception ex)
{
if (ex.InnerException != null && ex.InnerException is TimeoutException) {
throw ex.InnerException;
}
}
}
@SWarnberg same... Could you fix it?
Have a similar problem, some solution @tonerdo?
var shim = Shim
.Replace(() => Is.A<IDbConnection>().QueryFirstOrDefaultAsync<string>(
Is.A<string>(),
Is.A<object>(),
Is.A<IDbTransaction>(),
Is.A<int?>(),
Is.A<CommandType?>()))
.With(() => Task.Factory.StartNew(() => ""));
For support for async/await please see https://github.com/Miista/pose/issues/12
cc: @tonerdo @ashGHub @SWarnberg @dm-conti @OscarCanek @MariuszPL55 @alexzaytsev-newsroomly @ydemetriades @qjnz @NecromancerKing @lpatterson14