Nancy: Assistance with unit testing a module with a service locator

Created on 19 May 2016  路  1Comment  路  Source: NancyFx/Nancy

Prerequisites

  • [x] I have written a descriptive issue title
  • [x] I have verified that I am running the latest version of Nancy
  • [x] I have verified if the problem exist in both DEBUG and RELEASE mode
  • [x] I have searched open and closed issues to ensure it has not already been reported

    Description

So I currently have a module that derives from a base module that is using a service locator.

The service locator needs the TinyIocContainer set and that gets set in ConfigureRequestContainer in the Bootstrap.

Here is a snippit of what I am talking about:

public abstract class BaseModule : NancyModule
{
    protected ServiceLocator Locator => ServiceLocator.Instance;
    protected ISettingsService<PlexRequestSettings> Settings => Locator.Resolve<ISettingsService<PlexRequestSettings>>();
    protected string BaseUrl { get; set; }

    protected BaseModule()
    {
        var settings = Settings.GetSettings();
        var baseUrl = settings.BaseUrl;
        BaseUrl = baseUrl;

        var modulePath = string.IsNullOrEmpty(baseUrl) ? string.Empty : baseUrl;

        ModulePath = modulePath;
    }
}

So all of my modules are deriving from the BaseModule, but due to this I cannot seem to unit test it anymore and I am getting the following:

System.InvalidOperationException : Something went wrong when trying to satisfy one of the dependencies during composition, make sure that you've registered all new dependencies in the container and inspect the innerexception for more details.
  ----> Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type: Nancy.NancyEngine
  ----> Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type: Nancy.Routing.DefaultRequestDispatcher
  ----> Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type: Nancy.Routing.DefaultRouteResolver
  ----> Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type: Nancy.Routing.RouteCache
  ----> Nancy.TinyIoc.TinyIoCResolutionException : Unable to resolve type: PlexRequests.UI.Modules.ApiModule
  ----> System.NullReferenceException : Object reference not set to an instance of an object.

Here is an example of the Unit test i am referring to (Using NUnit):

[TestFixture]
public class ApiModuleTests
{
    private ConfigurableBootstrapper Bootstrapper { get; set; }

    [SetUp]
    public void Setup()
    {
        var requestMock = new Mock<IRequestService>();
        var settingsMock = new Mock<ISettingsService<PlexRequestSettings>>();
        Bootstrapper = new ConfigurableBootstrapper(with =>
        {
            with.Module<ApiModule>();
            with.Dependency(requestMock.Object);
            with.Dependency(settingsMock.Object);
            with.ApplicationStartup(
                (c, a) =>
                {
                    var loc = ServiceLocator.Instance; // Here I am trying to set the container for the service locator
                    loc.SetContainer(c);
                });
        });

    }

    [Test]
    public void GetAllRequests()
    {

        var browser = new Browser(Bootstrapper);

        var result = browser.Post("/api/requests", with =>
        {
            with.HttpRequest();
            with.Header("Accept", "application/json");
            with.Query("apikey","a");

        });

        Assert.That(HttpStatusCode.OK, Is.EqualTo(result.StatusCode));
    }

Any ideas how I can do this?

Most helpful comment

Please do not use the ServiceLocator pattern, it's cancer for code. Nancy was specifically designed to be service locator kryptonite. If you need dependencies in your module, please take them as constructor parameters instead, If you are using the default bootstrapper then your dependencies will automatically be registered for you. if you are using another bootstrapper then you can override the ConfigureApplicationContainer or ConfigureRequestContainer methods and setup your dependencies

>All comments

Please do not use the ServiceLocator pattern, it's cancer for code. Nancy was specifically designed to be service locator kryptonite. If you need dependencies in your module, please take them as constructor parameters instead, If you are using the default bootstrapper then your dependencies will automatically be registered for you. if you are using another bootstrapper then you can override the ConfigureApplicationContainer or ConfigureRequestContainer methods and setup your dependencies

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jgillich picture jgillich  路  7Comments

juniormayhe picture juniormayhe  路  4Comments

cody82 picture cody82  路  9Comments

epsitec picture epsitec  路  5Comments

Radzhab picture Radzhab  路  11Comments