When trying to unit test my web api project I am getting the error
{[Message, An error has occurred.]} ExceptionMessage, An error occurred when trying to create a controller of type 'ExampleController'. Make sure that the controller has a parameterless public constructor. {[ExceptionType, System.InvalidOperationException]} {[StackTrace, at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request) at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()]} {[InnerException, System.Web.Http.HttpError]}
Unit Test:
[TestFixtureSetUp]
public void TestsSetup()
{
_server = HttpRequestHelper.SetupHttpServerDefault();
}
[Test]
public void CanGetAllAddresses()
{
var client = new HttpClient(_server);
var request = HttpRequestHelper.CreateRequest("memory/address", HttpMethod.Get, ConfigurationManager.AppSettings["KeyUser"], string.Empty, ConfigurationManager.AppSettings["SecretUser"]);
using (HttpResponseMessage response = client.SendAsync(request).Result)
{
Assert.NotNull(response.Content);
}
}
I am registering my controllers within an nunit TestFixtureSetUp
function that involves this logic:
public static HttpServer SetupHttpServerDefault()
{
var config = new HttpConfiguration();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "memory/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var container = new Container();
container.Register<IAddressService, AddressService>();
var services = GlobalConfiguration.Configuration.Services;
var controllerTypes = services.GetHttpControllerTypeResolver().
GetControllerTypes(services.GetAssembliesResolver());
foreach (var controllerType in controllerTypes)
{
var registration = Lifestyle.Transient.
CreateRegistration(controllerType, container);
container.AddRegistration(controllerType, registration);
registration.SuppressDiagnosticWarning
(DiagnosticType.DisposableTransientComponent, "");
}
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver = new
SimpleInjectorWebApiDependencyResolver(container);
return new HttpServer(config);
}
My address controller starts out like this:
public class AddressController : BaseController
{
private readonly IAddressService _addressService;
public AddressController(IAddressService addressService)
{
_addressService = addressService;
}
}
When removing the controller parameters I am able to debug into the controller which tells me I am not injecting the dependencies into the controller correctly. I've looked over this post here that seems similar but I am unfamiliar with how I would explicitly declare my controllers. I tried using a similar method to my services but I did not work.
The solution for my particular problem was actually to register the dependency resolver on both the in memory HttpServer
that I am creating in the tests and on the GlobalConfiguration
as well. Above in the question you'll see the creation of the config
variable and then this is the code that fixed my issues:
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver =
new SimpleInjectorWebApiDependencyResolver(container);
Without the config.DependencyResolver
I wasn't able to connect to my projects controllers via:
using (HttpResponseMessage response = client.SendAsync(request).Result)
And without GlobalConfiguration.Configuration.DependencyResolver
I wasn't able to contact services locally in my test project. Hope this helps someone else!