Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I inject Db into Service classes when unit testing ServiceStack.OrmLite with NUnit?

I'm interested in writing unit tests (using NUnit) for some service classes created using ServiceStack, using the "New API" (inheriting from ServiceStack.ServiceInterface.Service). The services' Db property is properly auto-wired when hosted in an ASP.NET application using AppHost, but I can't seem to figure out the proper technique when running outside of that environment. I see a variety of testing-related namespaces and classes in ServiceStack but can't find a clear example where a service's Db property is getting injected, as opposed to simply setting up a connection factory directly and then calling the various IDbConnection extension methods (Insert, Select, etc.).

I have tried having my test class inherit from ServiceStack.ServiceInterface.Testing.TestBase and overriding its Configure method to register an IDbConnectionFactory (using ":memory:"), as well as setting OrmLiteConfig.DialectProvider = SqliteDialect.Provider; in my TestFixtureSetUp, but I continue to get a NullReferenceException when calling my service methods (at at ServiceStack.ServiceInterface.Service.get_Db()). It seems that the Funq container is not auto-wiring anything.

SQLite itself is properly set up, which I'm able to confirm with simpler unit tests that bypass my service classes and simply do direct IDbConnection calls.

What am I missing?

Edit

It appears that unit-testing ServiceStack services requires the existence of a host and a client, although it looks like there are ways to set this up to avoid the serialization cost (using the DirectServiceClient, as shown here) -- though I haven't succeeded in getting that to work in my case. I managed to get this working using an AppHostHttpListenerBase approach (see here) although it's more of an integration test than a unit one (and is accordingly slower).

like image 356
Nick Jones Avatar asked Jan 09 '13 19:01

Nick Jones


1 Answers

The docs on Testing shows a couple of different approaches for injecting dependencies.

If you look at the implementation for the base Service it just creates the Db from the IDbConnectionFactory:

private IDbConnection db;
public virtual IDbConnection Db
{
    get { return db ?? (db = TryResolve<IDbConnectionFactory>().OpenDbConnection()); }
}

That it just resolves from the local or Global IResolver IOC container:

public static IResolver GlobalResolver { get; set; }

private IResolver resolver;
public virtual IResolver GetResolver()
{
    return resolver ?? GlobalResolver;
}

public virtual T TryResolve<T>()
{
    return this.GetResolver() == null
        ? default(T)
        : this.GetResolver().TryResolve<T>();
}

So to inject your own dependencies (when using Service base class) you just need to configure a IAppHost with your dependencies your services need which you can do with:

using (var appHost = new BasicAppHost {
    ConfigureContainer = c => {
        c.Register<IDbConnectionFactory>(new ...);
    }
}.Init())
{
  //...    
}

Which you can then set on your service along with any of your own dependencies your service needs, e.g:

var service = appHost.ResolveService<MyService>();

Which will autowire all dependencies configured in your AppHost, you can also add your own adhoc test-specific dependencies via normal property access, e.g:

var service.MyDependency = new Mock<IMyDependency>().Object;

From then on you can just call and test your C# class methods as per usual:

var response = service.Get(new RequestDto { ... });
Assert.That(response.Result, Is.Equal("Expected Result from DB"));
like image 158
mythz Avatar answered Sep 25 '22 18:09

mythz