With WebAPI, you don't need access to the current resolver because the current dependency scope generally comes along with the inbound HttpRequestMessage
. That message is also what's responsible for generating the new request scope.
You can see the code for this in the System.Net.Http.HttpRequestMessageExtensions.GetDependencyScope
method.
One big thing you'll notice in WebAPI is that you don't actually need to set anything in global static values - that is, you don't need to set a global configuration/resolver because everything is instance-based now.
For testing, what this means is:
- Your setup will create an
HttpRequestMessage
with the appropriate dependency resolver and configuration. - Your teardown will dispose of the
HttpRequestMessage
which will, in turn, dispose the dependency scopes, etc. down the line. - Individual tests will use
HttpRequestMessage.GetDependencyScope()
if they need to do manual resolution of something and the request message will be used to coordinate/pass around the scope.
In a more concrete fashion, it might look like:
private HttpRequestMessage _request;
[SetUp]
public void SetUp()
{
var builder = new ContainerBuilder();
// Register stuff.
var container = builder.Build();
var resolver = new AutofacWebApiDependencyResolver(container);
var config = new HttpConfiguration();
config.DependencyResolver = resolver;
config.EnsureInitialized();
this._request = new HttpRequestMessage();
this._request.SetConfiguration(config);
}
[TearDown]
public void TearDown()
{
this._request.Dispose();
}
[Test]
public void Test()
{
// When you need to resolve something, use the request message
this._request.GetDependencyScope().GetService(typeof(TheThing));
}
What's nice about this is that you don't have to fight with global configuration settings or resetting static values after every test.
You might wonder why you'd pass around the whole request message rather than just the dependency resolver - the reason is that the request message is what coordinates and controls the lifetime of the dependency scope. Otherwise, when you call GetDependencyScope
multiple times, you'll get multiple different scopes rather than the same one as you'd expect.
Some things to consider from a design perspective:
- You might want to put the actual registrations of things into an Autofac module so it can be reused in both tests and in your
RegisterAndSetResolver
method without having to worry about global statics getting tampered with. - Instead of a
RegisterAndSetResolver
modifying the global static configuration, you might consider just setting the resolver on theHttpConfiguration
object that gets wired up in thatWebApiConfig.Register
method that WebAPI gives you. Take anHttpConfiguration
object in as a parameter and set the resolver on that rather than the global. - If you're doing every registration for everything in a unit test, your unit tests might be closer to "integration tests." You might consider looking at only what's required for the stuff you're testing and using a mock framework to register stubs rather than actually registering a boatload of "real stuff."
Anyway, HttpRequestMessage
is the way to go for WebAPI.