amphp / http-client

An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.
https://amphp.org/http-client
MIT License
704 stars 66 forks source link

Final HttpClient & DelegateHttpClient vs PHPunit #287

Closed Nessworthy closed 3 years ago

Nessworthy commented 3 years ago

XY is I'm trying to use an appropriate type across an app for a HTTP client. On top of this, I need to be able to mock the type chosen for unit testing. Unfortunately, I'm kind of stuck here - if I use HttpClient as the type, PHPUnit will tell me off for trying to mock a final class.

Alternatively, DelegateHttpClient doesn't seem like the right thing to use either since it has explicit notes about how it shouldn't be used.

Finally, I could set up some kind local interface & wrapper implementation, but then that still leaves untested code if the client can't be mocked. I'd have to also end up having to make request & response wrappers too which seems wrong.

I feel like this has probably been encountered before and there's a solution I'm missing.. is there a solution or am I fundamentally doing something wrong?

enumag commented 3 years ago

A possible solution (I think, didn't actually try) is to not bother with mocking the client but instead using a real HttpClient but with a custom or mocked ApplicationInterceptor which would handle what you need.

kelunik commented 3 years ago

You should mock DelegateHttpClient and construct an HttpClient with that mock. Then use the HttpClient in your application.

Instead, you can also register an ApplicationInterceptor as @enumag suggested.

Nessworthy commented 3 years ago

Much appreciated, both of you! Will close off as answered.

Nessworthy commented 3 years ago

Re-opening this actually, as there's a difference between HttpClient and DelegateHttpClient. The former only optionally expects a cancellation token in request, while the latter expects it. Linters are not liking this. Not having to pass NullCancellationToken into every http request would be nice. :(

enumag commented 3 years ago

Can you show us your current code? I mean creating and using the mock. I think there was a slight misunderstanding.

kelunik commented 3 years ago

That's exactly why HttpClient exists and why DelegateHttpClient shouldn't be used except for in interceptors. So you should use new HttpClient($mock) in your tests.

Nessworthy commented 3 years ago

So you should use new HttpClient($mock) in your tests.

100% my misunderstanding here, that would definitely work! Thanks 😓