Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If you want to unit test a ServiceStack Service in isolation there are a couple of different approaches you can take. The base <a href="https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Service.cs" rel="nofollow">Service</a> class itself is just a simple C# class which lets you define and inject dependencies manually or by using the built-in IOC container. </p> <p>We'll illustrate both approaches using this <a href="https://github.com/ServiceStack/ServiceStack/blob/master/tests/ServiceStack.WebHost.Endpoints.Tests/UnitTestExample.cs" rel="nofollow">simple unit test example</a> that tests this simple Service:</p> <h3>DTOs</h3> <pre><code>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 { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int? Age { get; set; } } </code></pre> <h3>Implementation</h3> <pre><code>public class SimpleService : Service { public IRockstarRepository RockstarRepository { get; set; } public List&lt;Rockstar&gt; Get(FindRockstars request) { return request.Aged.HasValue ? Db.Select&lt;Rockstar&gt;(q =&gt; q.Age == request.Aged.Value) : Db.Select&lt;Rockstar&gt;(); } public RockstarStatus Get(GetStatus request) { var rockstar = RockstarRepository.GetByLastName(request.LastName); if (rockstar == null) throw HttpError.NotFound("'{0}' is not a Rockstar".Fmt(request.LastName)); var status = new RockstarStatus { Alive = RockstarRepository.IsAlive(request.LastName) }.PopulateWith(rockstar); //Populates with matching fields return status; } } </code></pre> <p>This Service provides 2 operations, <code>FindRockstars</code> which makes db queries directly in the service class itself, and <code>GetStatus</code> which uses a repository instead for all its Data access.</p> <h2>Using an in-memory database</h2> <p>If you're accessing <code>Db</code> from directly within your service implementation you're going to want to make use of a real DB given the <a href="http://msdn.microsoft.com/en-us/library/system.data.idbconnection.aspx" rel="nofollow">ADO.NET IDbConnection</a> 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 <code>Container</code> in your <code>TestFixtureSetup</code>, e.g:</p> <h3>Test Setup</h3> <pre><code>private ServiceStackHost appHost; [TestFixtureSetUp] public void TestFixtureSetUp() { appHost = new BasicAppHost().Init(); var container = appHost.Container; container.Register&lt;IDbConnectionFactory&gt;( new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider)); container.RegisterAutoWiredAs&lt;RockstarRepository, IRockstarRepository&gt;(); container.RegisterAutoWired&lt;SimpleService&gt;(); using (var db = container.Resolve&lt;IDbConnectionFactory&gt;().Open()) { db.DropAndCreateTable&lt;Rockstar&gt;(); db.InsertAll(SeedData); } } [TestFixtureTearDown] public void TestFixtureTearDown() { appHost.Dispose(); } </code></pre> <p>With everything setup we can now test the service just like a normal C# class in isolation independently of ServiceStack itself:</p> <pre><code>[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&lt;SimpleService&gt;(); 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 =&gt; 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&lt;HttpError&gt;(() =&gt; service.Get(new GetStatus { LastName = "Unknown" })); } </code></pre> <h2>Manually injecting dependencies</h2> <p>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 <a href="https://github.com/Moq/moq" rel="nofollow">Moq</a> instead.</p> <pre><code>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&lt;HttpError&gt;(() =&gt; service.Get(new GetStatus { LastName = "Hendrix" })); } </code></pre> <p>This example doesn't need a container as we're injecting all the dependencies manually. I've also added this example to the <a href="https://github.com/ServiceStack/ServiceStack/wiki/Testing" rel="nofollow">Testing wiki</a> docs.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload