3
votes

I recently took a .Net project over which exposes DAOs from a Microsoft SQL Database via ServiceStack(3.9.71) REST API. Since I am gonna refactor some parts I want to unit test (at least) all servicestack services. For a better understanding I quickly draft how the implementation works.

Each Service contains a property of type DBService which encapsulates all database accesses of all services. Unfortunately this is a concrete class which makes it hard to mock. The DI.Container wrappes ServiceStack's IOC.

public class SomeService : Service
{
    public DBService { get { return DI.Container.Resolve<DBService>(); } } 

    public object Get(SomeDataClass class)
    {
       var response = DBService.SomeServiceGet();
       return response;
    }

    // other code omitted

}

The DBService looks like this (draft):

public class DBService 
{
     public IDbConnectionFactory DBFactory { get { return DI.Container.Resolve<IDbConnectionFactory>(); } }
    public SomeServiceResponse SomeServiceGet()
    {
       //DB Access here...
       // ...
    }
    public SomeOtherServiceResponse SomeOtherServiceGet()
    {
       //...
    }

    // following about 30 other methods for all the services (POST,GET,PUT etc)
}

I read the detailed response to this question but I was not able to create and initialize a BasicAppHost in ServiceStack 3.9.71 since it immediately threw a System.TypeLoadExceptionMethod 'get_VirtualPathProvider'.

On the other hand I was thinking that I do not actually need a BasicAppHost. I just have to unit test the DBService and then the servicestack services with a somehow mocked DBService. The only problem I have is that DBService is not an interface and that I am actually not sure how to deal (mock) with the SQL database and the IOC.

[UPDATE]

Unfortunately I am still not able to test a service since I can not just new the service in my test. If I do so I get:

System.TypeLoadExceptionCould not load type 'ServiceStack.ServiceHost.IService' from assembly

Here is my test:

[Fact]
public void SomeDataTest()
{
   var serviceUnderTest = new SomeService();
   var response = serviceUnderTest.Get(new SomeDataClass());

   Assert.NotNull(response);
}

I guess the problem is that the services strongly uses alot of properties which are injected via the IOC. How can I mock that? Creating a BasicAppHost and retrieving the service from there also does not work which I already mentioned.

1
Once neither of the classes in question are sealed then you can create you own class that inherits them and overrides or new up the behavior desired for testing. It is hard to mock but not impossible.Nkosi
so I actually don't have to care about the IOC injection of the IDbConnectionFactory? I am also wondering if it its a better approach so implement an interface for the DBService so I can easily mock it.zlZimon
Yes abstracting the DbService would improve testability greatly and you should consider constructor injection as apposed to the Service Locator anti-pattern you are usingNkosi
Show the unit test that is failing. along with any related classes as a minimal reproducible example that can be used to reproduce the problem in finding a solution.Nkosi

1 Answers

0
votes

If you are just testing your service class, then you can directly mock any dependencies:

[Fact]
public void SomeDataTest(
{
    var serviceUnderTest = new SomeService();

    var logger = new Mock<ILogger>();  // Rhino mocks fashion.
    serviceUnderTest.Logger = logger.Object;

    var response = serviceUnderTest.Get(new SomeDataClass());

   Assert.NotNull(response);
}

There's an page in their older docs here about integration testing in case you want to test the AppHost

Edit: there's an example of mocking the service dependencies here.