-
-
Notifications
You must be signed in to change notification settings - Fork 388
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
Allow HttpTest to work correctly when different tests are running in parallel #67
Comments
There's a notable limitation in how HttpTest works: it puts Flurl in test mode globally so it is not thread-safe. The result if is that if you try to run tests in parallel, you could definitely run into issues. Are you running tests in parallel? |
Yes, in parallel. How to get around this? There are a way? |
There is no workaroud currently. I will keep this issue open and explore some possibilities when I have some time. |
Do you think about |
This could be tricky. Since we're usually dealing with async code, I think you'll want to look at Logical CallContext for this. http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html Even then, if the code a user is testing is multithreaded this could break down. I'll be interested to see what you come up with though. |
If this isn't ready I would be ok with shelving it for later. (1.1?) |
@tmenier I want to fix it ASAP. And I am testing new packages with Xamarin and win10 yet. There are problem with it. |
Why did you mark this issue ready? |
No idea how that happened. I moved it back. By the way, I'm going to try and wrap up #48 and some misc refactoring this week, then I'll be ready for 1.0. Any thoughts on when you think you'll be ready? No rush, I'll actually be away most of next week anyway. |
@tmenier I think, think and I see that only one right way is remove a static global configuration for Flurl.Http. Global static config pattern is antipattern. Like: public void ConfigureServices(IServiceCollection services)
{
services.AddFlurlClient(options =>
options.Timeout(Configuration.GetConnectionString("Flurl:Timeout")));
} HttpTest too be able working with DI. I see 2 cases which can not works with global static config:
|
The # 1 goal of Flurl is to save keystrokes. The trade-off is that some of the most keystroke-saving patterns do not lend themselves well to DI. For example, what exactly do you inject into a class or method that does this? await "http://api.com".GetAsync(); I knew from the start this would create a problem for testing, which is why I created the test helpers. Parallel testing has become much more common since I started this, so I agree this is an issue that should be addressed or clearly documented as a limitation. Your second concern (clients in different threads) is addressed by the fact that each client gets a copy the global config (via Which leaves testing. There's nothing preventing someone from using DI and Flurl in the same project. They would just wrap the details of the HTTP calls into service objects that can be injected/mocked/stubbed. Use of Flurl would be an implementation detail of the "real" implementation. I think this is an appropriate architecture for bigger applications. For simpler cases, which Flurl provides helpers for, I think the ease of use comes with the tradeoff of no parallel testing, or we try to fix this by storing the response queue and call log on the logical call context rather than in global scope. I think this would be worthwhile. |
@tmenier IOC injects option into FlurlClient when it was created. public FlurlClient(IOptions options){}
services.AddFlurlOptions(new ...)
.AddFlurlClient(); In diff situation options maybe different. |
@tmenier Please answer what do you think about "How to do that without global FlurlClient?"? |
Sorry. What IoC container are you using? Doesn't it allow some sort of factory method for resolving a type? In that method I would create a FlurlClient, configure its settings via the Maybe all you really want is a new FlurlClient constructor that takes a settings object as a parameter? I would be open to adding that. It fits the IoC resolution pattern a little better, event though I think using a factory method like I described is an ok work-around. |
@kroniak I've taken a break from working on Flurl but I'm ready to get back at it. Parallel testing is my top priority. I tried storing But I also want to make sure that Flurl is DI friendly. I still think you would have to give up syntax like
Thoughts? |
I see one way - It's isolating static fields for threads. In different threads will be different options. Thread can change it with FlurlHttp.Settings or gets default. |
The problem with using thread local storage is that we're dealing with async code and often not resuming on the same thread, so I don't think that will work here. But this is exactly what logical call context (and the newer AsyncLocal) were created to address. |
Parallel tests are working (except on PCL)! I think this test proves it. Here's the platform-specific call context stuff if you're curious. Other suggested changes moved to #146. Prerelease for Flurl.Http 1.1 coming shortly. |
Please test the prerelease https://www.nuget.org/packages/Flurl.Http/1.1.0-pre |
@tmenier Great job! I am testing! |
@tmenier I have no issue with parallel testing! |
The case:
In one test class I use some code like:
and in the other test class:
I have many tests and when I run them all together real test sometimes uses HttpTest responces and throw exceptions.
It's bug or I does not understand something?
The text was updated successfully, but these errors were encountered: