Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mock server not answer if integrated in Xamarin UITest project #534

Closed
DellaMoraWalter opened this issue Nov 6, 2020 · 9 comments
Closed
Labels

Comments

@DellaMoraWalter
Copy link

I'm encountering a problem using WireMock.Net in a Xamarin UITest project, currently with Android (iOS not tested yet).
I'm trying to mock my backend, the WireMock instance is created in the UITest project but even if the server is active, the calls are not processed.

I've attached a full example for reproduce the problem, for use remember to align the ip address of the wiremock server with your machine ip address.
If you start the only test defined in MockBackendTests, this fail after the timeout because the call to the wiremock server never gets an answer.

In the solution you can find the 'MockBackendConsole' application that can create an identical instance of wiremock server.
To try it you have to:

  1. comment the 'USE_LOCAL_SERVER' compiler directive on top of Tests.cs
  2. start manually 'MockBackendConsole'
  3. restart the test, in this way it complete succesfully.

I've integrated the solution with the last (v 1.3.5) wiremock.net source code, and set a breackpoint in WireMockMiddleware.cs.
If the mock server is create inside the UITest project, the 'InternalInvoke' function is never called.

Unfortunately I don't understand the problem behind this behavior.
Thanks for support.

MockBackend.zip

@xadvfh
Copy link

xadvfh commented Nov 26, 2020

@DellaMoraWalter for some reason WireMock.Net does not work when you set breakpoints. See #510 I also would love to get to the bottom of this.

@DellaMoraWalter
Copy link
Author

@xadvfh in my attached sample solution the breakpoint works correctly if the wikemock server is started with the console application but don't works if the wiremock server is started inside the UITest project.
So my problem (I think) is not the breackpoints.
Onestly, I'm not sure about how UITest works. Where is executed UITest code, on my machine or in the android simulator?
If is executed in the android simulator, wiremock server has to works or there are restrictions on communication that inibits something?

@StefH
Copy link
Collaborator

StefH commented Dec 5, 2020

I guess it could also be related to UI threads and background threads in a Xamarin project.
(Maybe starting WireMock.Net in a separate thread/task could help?)

@kcamp
Copy link

kcamp commented Dec 15, 2020

@DellaMoraWalter I am pretty sure I came across this same problem today (and solved it) as I found this issue while doing some research.
My problem looks/acts just like what you're describing (and is also a .NET 4.6.1 project, although we're using xUnit).

I was able to reproduce this in Visual Studio 16.8.3 (for reference only, I don't believe this actually matters).

In our case, we're setting up WireMock to emulate a remote API. The behavior was very similar; we could make the request using our HttpClient, but ultimately we'd receive a timeout on the client side, with no apparent response or reaction from WireMock. Inspections for netstat -an | findstr <port> showed that the WireMock implementation was listening correctly, but didn't seem to be handling the request/response cycle fully. Similar inspections in Fiddler seemed to indicate the request was being processed, but the response was never fully completed.

Ultimately, I was able to view an unhandled exception in the WireMock internals during the teardown.

"Could not load file or assembly 'System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. 
The system cannot find the file specified.":"System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"
....
at System.IO.Pipelines.PipeCompletion.GetCallbacks()
   at System.IO.Pipelines.PipeCompletion.TryComplete(Exception exception)
   at System.IO.Pipelines.Pipe.CompleteWriter(Exception exception)
   at System.IO.Pipelines.Pipe.DefaultPipeWriter.Complete(Exception exception)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1OutputProducer.Abort(Exception error)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Abort(Exception error)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection.Abort(Exception ex)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.HttpConnectionManagerShutdownExtensions.<>c__DisplayClass1_0.<AbortAllConnectionsAsync>b__0(HttpConnection connection)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.HttpConnectionManager.Walk(Action`1 callback)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure.HttpConnectionManagerShutdownExtensions.<AbortAllConnectionsAsync>d__1.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<StopAsync>d__23.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.<StopAsync>d__23.MoveNext()
   at Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer.Dispose()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.Dispose()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.Dispose()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.<StopAsync>d__31.MoveNext()
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.Dispose()
   at Microsoft.AspNetCore.Hosting.Internal.WebHost.Dispose()
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__5.MoveNext()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.WebHostExtensions.<RunAsync>d__4.MoveNext()

Inspecting the Fusion logs, I found that there were two assemblies that were not correctly loading.
System.Buffers and System.Numerics.Vectors.

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  C:\git\WireMock.Net\examples\WireMock.Net.Console.Net461.Classic\bin\Debug\WireMock.Net.Console.Net461.Classic.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
 (Fully-specified)
LOG: Appbase = file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = WireMock.Net.Console.Net461.Classic.exe
Calling assembly : System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\git\WireMock.Net\examples\WireMock.Net.Console.Net461.Classic\bin\Debug\WireMock.Net.Console.Net461.Classic.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.Buffers, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Buffers.DLL.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Buffers/System.Buffers.DLL.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Buffers.EXE.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Buffers/System.Buffers.EXE.
LOG: All probing URLs attempted and failed.

Adding just the redirect for the System.Buffers assembly will result in WireMock immediately returning a 504 status code; further analysis shows the issue with System.Numerics.Vectors

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  C:\git\WireMock.Net\examples\WireMock.Net.Console.Net461.Classic\bin\Debug\WireMock.Net.Console.Net461.Classic.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: DisplayName = System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
 (Fully-specified)
LOG: Appbase = file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = WireMock.Net.Console.Net461.Classic.exe
Calling assembly : System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\git\WireMock.Net\examples\WireMock.Net.Console.Net461.Classic\bin\Debug\WireMock.Net.Console.Net461.Classic.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.Numerics.Vectors, Version=4.1.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Numerics.Vectors.DLL.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Numerics.Vectors/System.Numerics.Vectors.DLL.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Numerics.Vectors.EXE.
LOG: Attempting download of new URL file:https:///C:/git/WireMock.Net/examples/WireMock.Net.Console.Net461.Classic/bin/Debug/System.Numerics.Vectors/System.Numerics.Vectors.EXE.
LOG: All probing URLs attempted and failed.

Adding assembly binding redirects for both of these assemblies to the app.config of the project made WireMock work correctly, at least for the two machines in our organization that were experiencing the same behavior.

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="4.0.2.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <bindingRedirect oldVersion="4.0.0.0-4.1.4.0" newVersion="4.1.4.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>

I have pushed a very simple repro/fix to a branch kcamp@36f446b; I did not attempt to run your tests @DellaMoraWalter, but, looking at your attached MockBackend.zip and general description of the problem, I suspect it might fix your problem. In fact, re-reading your last comment about "it works if it is launched from the console", I am positive this is the case (and that it will fix your tests), since I see that your Console app.config does contain the correct redirects already.

In that branch, kcamp@36f446b, the steps to repro are basically this:

  1. From Visual Studio 2019, run the WireMock.Net.Console.Net461.Classic application from the current fa08d0e revision.
  2. Using Fiddler/Postman/cUrl, invoke a request to one of the configured endpoints/listeners. I used http:https://localhost:9091/random for my tests.
  3. Observe that the response never returns.
  4. Introduce the changes (referenced in my commit, above) to include the redirects.
  5. Build + run the Net461.Classic application with these changes
  6. Repeat step 2, but observe that WireMock returns a correct response with a status of 200 OK with the binding redirects in place.

(The endpoint being invoked is immaterial, I was able to observe the same issues as a matter of the hosting, not so much individual implementations)

This seems to be vaguely familiar to the behavior described in #393 as well

I found that running WireMock with Kestrel from within this the Visual Studio test runner (via Test Explorer) seems to hang in an odd way, in that HTTP calls made to the mock never complete.

@StefH This does seem like some sort of issue with the way this is behaving in .NET 4.6.1; not to say it's not purely environmental in our cases. If there is any additional detail I can provide to help diagnose or do a deeper dive to understand the why, please let me know, I'd be happy to provide any details I might be able to.

@StefH
Copy link
Collaborator

StefH commented Dec 16, 2020

Hello @kcamp, thank you for the research.

@DellaMoraWalter can you try if this workaround solves your issue?

If this indeed solves the issue, I'll add this to a wiki page.

(Note that issue also looks a bit like this one #437)

@DellaMoraWalter
Copy link
Author

@kcamp, thanks for your very detailed analisys. @StefH, sure I will try the suggested workaround but I need some days because I'm in the middle of a sprint with totally different arguments. I will report you the results of my tests as soon as possible.

@DellaMoraWalter
Copy link
Author

I've tried the solution proposed by @kcamp and it works perfectly. Referring to the project I've attached to my first post, it was enough to add to the MockBackendTests project an App.config writted like suggested. @kcamp, many thanks again for your help.

@StefH
Copy link
Collaborator

StefH commented Dec 20, 2021

@StefH
Copy link
Collaborator

StefH commented Dec 24, 2021

@DellaMoraWalter

I've added ConfigureAwait(false) to all await calls, so maybe this will solve your issue.

I'm closing this issue now, a new official version will be released in some days.

#704

@StefH StefH closed this as completed Dec 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants