Testing

The tests in ServiceStack.WebHost.Endpoints.Tests show good examples of how to create stand-alone integration tests that just use a self-hosted HttpListener AppHost.

Quick Mix

Use mix to quickly create a .NET 6 Integration Test project:

$ x mix init-test

Or if you need to create a source compatible .NET 6 and .NET v4.72 Integration Test project:

$ x mix init-test2

Example Stand-alone Integration tests

Integration Testing

If your test project is targeting netcore, AppSelfHostBase is available in the ServiceStack.Kestrel package.

The CustomerRestExample.cs shows an example of a stand-alone integration test. Integration tests in ServiceStack just involves starting a standard self-host ServiceStack Instance when the Test Fixture Starts up and disposing it when it tears down. Your integration tests can then communicate with the self-host exactly the same as if it were a remote ServiceStack instance (since that's all it is), e.g:

//Create your ServiceStack AppHost with only the dependencies it needs
public class AppHost : AppSelfHostBase
{
    public AppHost() : base("Customer REST Example", typeof(CustomerService).Assembly) {}

    public override void Configure(Container container)
    {
        container.Register<IDbConnectionFactory>(c => 
            new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider));

        using var db = container.Resolve<IDbConnectionFactory>().Open();
        db.CreateTableIfNotExists<Customer>();
    }
}

//Add Service Contract DTO's and Data Models
[Route("/customers", "GET")]
public class GetCustomers : IReturn<GetCustomersResponse> {}

public class GetCustomersResponse
{
    public List<Customer> Results { get; set; } 
}

[Route("/customers", "POST")]
public class CreateCustomer : IReturn<Customer>
{
    public string Name { get; set; }
}

public class Customer
{
    [AutoIncrement]
    public int Id { get; set; }

    public string Name { get; set; }
}

//Implement your Service Contracts
public class CustomerService : Service
{
    public object Get(GetCustomers request)
    {
        return new GetCustomersResponse { Results = Db.Select<Customer>() };
    }

    public object Post(CreateCustomer request)
    {
        var customer = new Customer { Name = request.Name };
        Db.Save(customer);
        return customer;
    }
}

//Write your Integration tests
public class CustomerRestExample
{
    const string BaseUri = "http://localhost:2000/";
    ServiceStackHost appHost;

    public CustomerRestExample()
    {
        //Start your AppHost on OneTimeSetUp
        appHost = new AppHost() 
            .Init()
            .Start(BaseUri);
    }

    [OneTimeTearDown]
    public void OneTimeTearDown() => appHost.Dispose();

    /* Write your Integration Tests against the self-host instance */

    [Test]
    public void Can_GET_and_Create_Customers()
    {
        var client = new JsonServiceClient(BaseUri);

        //GET /customers
        var all = client.Get(new GetCustomers());
        Assert.That(all.Results.Count, Is.EqualTo(0));

        //POST /customers
        var customer = client.Post(new CreateCustomer { Name = "Foo" });
        Assert.That(customer.Id, Is.EqualTo(1));

        //GET /customers
        all = client.Get(new GetCustomers());
        Assert.That(all.Results.Count, Is.EqualTo(1));
    }
}

Unit testing

If you want to unit test a ServiceStack Service in isolation there are a couple of different approaches you can take. The base Service class itself is just a simple C# class which lets you define and inject dependencies manually or by using the built-in IOC container.

We'll illustrate both approaches using this simple unit test example that tests this simple Service:

// DTOs
public class FindRockstars
{
   public int? Aged { get; set; }
   public bool? Alive { get; set; }
}

public class GetStatus
{
   public string LastName { get; set; }
}

public class RockstarStatus
{
   public int Age { get; set; }
   public bool Alive { get; set; }
}

public class Rockstar
{
   [AutoIncrement]
   public int Id { get; set; }
   public string FirstName { get; set; }
   public string LastName { get; set; }
   public int? Age { get; set; }
}

// Implementation
public class SimpleService : Service
{
   public IRockstarRepository RockstarRepository { get; set; }

   public List<Rockstar> Get(FindRockstars request)
   {
      return request.Aged.HasValue
          ? Db.Select<Rockstar>(q => q.Age == request.Aged.Value)
          : Db.Select<Rockstar>();
   }

   public RockstarStatus Get(GetStatus request)
   {
      var rockstar = RockstarRepository.GetByLastName(request.LastName);
      if (rockstar == null)
          throw HttpError.NotFound($"'{request.LastName}' is not a Rockstar");

      var status = new RockstarStatus
      {
          Alive = RockstarRepository.IsAlive(request.LastName)
      }.PopulateWith(rockstar); //Populates with matching fields

      return status;
   }
}

This Service provides 2 operations, FindRockstars which makes db queries directly in the service class itself, and GetStatus which uses a repository instead for all its Data access.

Using an in-memory database

If you're accessing Db from directly within your service implementation you're going to want to make use of a real DB given the ADO.NET IDbConnection requires a lot of effort to mock. You can do this in the same way you would register your dependencies in ServiceStack itself, by using the built-in IOC. For a unit test we can do this without an AppHost by just use a new Container in your OneTimeSetUp, e.g:

Test Setup

private ServiceStackHost appHost;

[OneTimeSetUp]
public void OneTimeSetUp()
{
    appHost = new BasicAppHost().Init();
    var container = appHost.Container;

    container.Register<IDbConnectionFactory>(
        new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider));

    container.RegisterAutoWiredAs<RockstarRepository, IRockstarRepository>();

    container.RegisterAutoWired<SimpleService>();

    using (var db = container.Resolve<IDbConnectionFactory>().Open())
    {
        db.DropAndCreateTable<Rockstar>();
        db.InsertAll(SeedData);
    }
}

[OneTimeTearDown]
public void OneTimeTearDown() => appHost.Dispose();

With everything setup we can now test the service just like a normal C# class in isolation independently of ServiceStack itself:

[Test]
public void Using_in_memory_database()
{
    //Resolve the autowired service from IOC and set Resolver for the base class
    var service = appHost.Container.Resolve<SimpleService>(); 

    var rockstars = service.Get(new FindRockstars { Aged = 27 });

    rockstars.PrintDump(); //Print a dump of the results to Console

    Assert.That(rockstars.Count, Is.EqualTo(SeedData.Count(x => x.Age == 27)));

    var status = service.Get(new GetStatus { LastName = "Vedder" });
    Assert.That(status.Age, Is.EqualTo(48));
    Assert.That(status.Alive, Is.True);

    status = service.Get(new GetStatus { LastName = "Hendrix" });
    Assert.That(status.Age, Is.EqualTo(27));
    Assert.That(status.Alive, Is.False);

    Assert.Throws<HttpError>(() =>
        service.Get(new GetStatus { LastName = "Unknown" }));
}

Manually injecting dependencies

If you prefer your unit tests not to use an in-memory database, you can instead choose to mock your dependencies. In this example we'll use a stand-alone Mock, but you can reduce boilerplate by using mocking library like Moq instead.

public class RockstarRepositoryMock : IRockstarRepository
{
    public Rockstar GetByLastName(string lastName)
    {
        return lastName == "Vedder"
            ? new Rockstar(6, "Eddie", "Vedder", 48)
            : null;
    }

    public bool IsAlive(string lastName)
    {
        return lastName == "Grohl" || lastName == "Vedder";
    }
}

[Test]
public void Using_manual_dependency_injection()
{
    var service = new SimpleService
    {
        RockstarRepository = new RockstarRepositoryMock()
    };

    var status = service.Get(new GetStatus { LastName = "Vedder" });
    Assert.That(status.Age, Is.EqualTo(48));
    Assert.That(status.Alive, Is.True);

    Assert.Throws<HttpError>(() =>
        service.Get(new GetStatus { LastName = "Hendrix" }));
}

This example doesn't need a container as we're injecting all the dependencies manually.

Testing ServiceStack classes in Unit Tests

Much of ServiceStack functionality assumes there's an AppHost is available which for Unit Tests you can just use an In Memory AppHost, e.g:

[Test]
public void My_unit_test()
{
    using (new BasicAppHost().Init())
    {
        //test ServiceStack classes
    }
}

If preferred this can be set up once per test fixture following this pattern:

public class MyUnitTests
{
    ServiceStackHost appHost;
    public MyUnitTests() => appHost = new BasicAppHost().Init();

    [OneTimeTearDown]
    public void OneTimeTearDown() => appHost.Dispose();

    [Test]
    public void My_unit_test()
    {
        //test ServiceStack classes
   }
}

Community Resources

Stack Overflow