I created a web API project using Ninject, and I used the detailed description here to get it working with the latest version of the web API. Everything is working fine, but now I'm trying to write some tests.
I use in-memory hosting to run the project for tests, as described here , since I have a DelegatingHandler that does authentication and then sets the property in the request message that is used by all Api controllers.
So, I have a base class for my tests and there is a SetUp method, where I configured HttpServer and a configuration that I took quite a bit from my Ninject working code:
[SetUp] public void Setup() { bootstrapper = new Bootstrapper(); DynamicModuleUtility.RegisterModule( typeof(OnePerRequestHttpModule)); DynamicModuleUtility.RegisterModule( typeof(NinjectHttpModule)); bootstrapper.Initialize(CreateKernel); var config = new HttpConfiguration(); config.Routes.MapHttpRoute("Login", "api/auth/token", new { controller = "Users", action = "Login" }); config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always; config.DependencyResolver = new NinjectResolver(CreateKernel()); config.MessageHandlers.Add( new AuthenticationHandler(CreateUserManager())); Server = new HttpServer(config); }
This is how I create MoqMockingKernel :
private static IKernel CreateKernel() { var kernel = new MoqMockingKernel(); kernel.Bind<Func<IKernel>>() .ToMethod(ctx => () => new Bootstrapper().Kernel); kernel.Bind<IHttpModule>() .To<HttpApplicationInitializationHttpModule>(); RegisterServices(kernel); GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel); return kernel; }
And this is how I register the objects used:
private static void RegisterServices(IKernel kernel) { kernel.Bind<IUserManager>().ToMock(); kernel.Bind<UsersController>().ToSelf(); }
Until I test the controller as such, I want the correct instance to call it, so I bind it to ToSelf. I must admit that I assume this is correct. This is a test example:
public void UserCannotLogin() { System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(Server); string json = string.Format( "{{ \"Username\": \"{0}\", \"Password\": \"{1}\" }}", "wrong", "wrong"); HttpRequestMessage request = CreateRequest(@"api/auth/token", json, HttpMethod.Get); Action action = () => client.SendAsync(request); using (var response = client.SendAsync(request).Result) { response.StatusCode.Should() .Be(HttpStatusCode.Unauthorized); } }
Basically, I get error 404. When I debug it, it goes to my DelegatingHandler , but it doesn't go to my controller.
I get the feeling that I basically missed the point here, and maybe I wonโt even be able to do what I'm trying to do, but if someone has suggestions for how to do this, or another way to achieve the same, I all ears.
Update. I think this is because the default behavior of MockingKernel is to provide Mock unless otherwise specified, therefore it returns Mock from IHttpControllerSelector . I set a couple of default ones by default:
kernel.Bind<IHttpControllerSelector>() .To<DefaultHttpControllerSelector>(); kernel.Bind<IContentNegotiator>() .To<DefaultContentNegotiator>();
It still does not work, I think, because there are no formatters. I will try it tomorrow and see if I will get me there.