Dependent injection – How to make the self-trail with IOC for web-API integration test?

I have spent hints from here to propose this integration test for my new Web Api project. I am trying to build a rest web service, and I have a help client, I intend Publish it to API users. This is the ExampleClientHelper type there. Oh, by the way, it’s all connected to the ValuesController that provides project templates for the MVC4 Web Api Visual Studio project-I keep it simple, and I stick to this. < p>

ExampleClientHelper replaces all requests/responses in the above reference example. It uses RestSharp internally.

[Test]
[Ignore ]
public void ValuesHelper_ShouldReturn_value1_And_value2_AsTypedObject()
{
// IoC prep
var builder = new ContainerBuilder();
var container = builder.Build();

// web server prep
var baseUri = new Uri("http://localhost:8080");
var config = new HttpSelfHostConfiguration(baseUri);
config .DependencyResolver = new AutofacWebApiDependencyResolver(container);

// yes, the routing needs to be copied over. it's not compatible with the MVC routes
config.Routes.MapHttpRoute("Api", "api/{controller}/{id}",
new {id = RouteParameter.Optional, namespaces = ne w[] {typeof(ValuesController).Namespace} });

// start the server and make a request
new HttpSelfHostServer(config)
.OpenAsync()
.ContinueWith(task =>
{
var client = new ExampleClientHelper(baseUri);
var values ​​= client.GetValues();

// then test the response
Assert.AreEqual("value1", values.ElementAt(0));
Assert.AreEqual("value2", values.ElementAt(1));
})< br /> .Wait();
}

As long as the ValuesController is not modified, the above code can work normally. That is. It still has an implicit parameterless constructor.

< p>The problem I have is that when I modify it to require dependencies, the self-host server seems to be unable to instantiate my ValuesController. The problem is that, regardless of whether the Autofac DependencyResolver is connected or not, I get the same exception from the response from the assistant client .This is the content returned in the response content. Because of RestSharp, it is formatted as JSON:

{“ExceptionType”:”System.ArgumentException”,”Message”: ”Type’Embed.ECSApi.RestServer.Controllers.ValuesController’ does not have a default constructor”,”StackTrace”:” at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator .Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)”}

Obviously, the autonomous server is trying to create a ValuesController, but it can’t. Why? I thought I connected the DependencyResolver correctly. I was expecting an Autofac exception instead of complaining about my unconfigured dependencies.

It looks like you forgot to register the controller with the container, and Web API is trying to create an instance for you.

var builder = new ContainerBuilder();

// Register API controllers using assembly scanning.
builder.RegisterApiControllers(typeof(ValuesController).Assembly);

var container = builder.Build();

You can also register a single controller if needed.

I have spent hints from here to propose this integration test for my new Web Api project. I’m trying to build a rest web service, and I have a help client that I intend to publish to API consumers. This is the ExampleClientHelper type there. Oh, by the way, this is all connected to MVC4 Web Api Visual The Studio project provides the ValuesController of the project template – I keep it simple, and I stick to this.

ExampleClientHelper replaces all requests/responses in the above reference example. It uses RestSharp internally.

[Test]
[Ignore]
public void ValuesHelper_ShouldReturn_value1_And_value2_AsTypedObject()
{
// IoC prep
var builder = new ContainerBuilder();
var container = builder.Build();

// web server prep
var baseUri = new Uri("http://localhost:8080");
var config = new HttpSelfHostConfiguration(baseUri);
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

// yes, the routing needs to be copied over. it's not compatible with the MVC routes
config.Routes.MapHttpRoute("Api", "api/{controller}/{id}",
new {id = RouteParameter.Optional, namespaces = new[] {typeof(ValuesController).Namespace} });

// start the server and make a request
new HttpSelfHostServer(config)< br /> .OpenAsync()
.ContinueWith(task =>
{
var client = new ExampleClientHelper(baseUri);
var values ​​= client.GetValues();

// then test the response
Assert.AreEqual("value1", values.ElementAt(0));
Assert.AreEqual("value2", values.ElementAt(1) );
})
.Wait();
}

As long as the ValuesController is not modified, the above code will work properly. That is. It still has an implicit parameterless constructor.

The problem I encountered is that when I modify it to require When relying, the self-host server seems to be unable to instantiate my ValuesController. The problem is that no matter whether the Autofac DependencyResolver is connected or not, I get the same exception from the response from the assistant client. This is the content returned in the response content, due to RestSharp, formatting As JSON:

{"ExceptionType":"System.ArgumentException","Message":"Type'Embed.ECSApi.RestServer.Controllers.ValuesController' does not have a default constructor”,”StackTrace”:” at System.Linq.Expressions.Expression.New(Type type) at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType) at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)”}

It is obvious that the autonomous server is trying to create a ValuesController, but it cannot .Why? I thought I connected the DependencyResolver correctly. I was expecting an Autofac exception instead of complaining about my unconfigured dependencies.

It looks like you forgot to register the controller with the container , Web API is trying to create an instance for you.

var builder = new ContainerBuilder();

// Register API controllers using assembly scanning.
builder.RegisterApiControllers(typeof(ValuesController).Assembly);

var container = builder.Build();

You can also register a single Controller.

Leave a Comment

Your email address will not be published.