2013-02-09 57 views
7

我有这样的服务:单元测试的HTTPRequest头与ServiceStack

public class PlayerService : Service 
{ 
    public IPlayerAppService PlayerAppService { get; set; } 

    public PlayerService (IPlayerAppService service) 
    { 
     if (service == null) 
      throw new ArgumentException ("Service null"); 

     PlayerAppService = service; 
    } 

    public object Post (PlayerDTO request) 
    { 
     var newPlayer = new PlayerResponse() 
     { 
      Player = PlayerAppService.SendPlayerLocation(request.Position.Latitude, request.Position.Longitude) 
     }; 

     return new HttpResult (newPlayer) 
     { 
      StatusCode = System.Net.HttpStatusCode.Created, 
      Headers = 
      { 
       { HttpHeaders.Location, base.Request.AbsoluteUri.CombineWith(newPlayer.Player.Id.ToString()) } 
      } 
     }; 
    } 
} 

我手动验证了定位和响应看起来与我对这个服务的部署是正确的。我想弄清楚如何进行单元测试。我写了这样一个测试:

[TestFixture] 
public class PlayerServiceTests 
{ 
    AppHost appHost; 

    [TestFixtureSetUp] 
    public void TestFixtureSetUp() 
    { 
     appHost = new AppHost(); 
     appHost.Init(); 
     appHost.Start ("http://localhost:1337/"); 
    } 

    [TestFixtureTearDown] 
    public void TestFixtureTearDown() 
    { 
     appHost.Dispose(); 
     appHost = null; 
    } 

    [Test] 
    public void NewPlayer_Should_Return201AndLocation() 
    { 
     // Arrange 
     PlayerService service = new PlayerService (appHost.TryResolve<IPlayerAppService>()); 

     // Act 
     HttpResult response = (HttpResult)service.Post (It.IsAny<PlayerDTO>()); 

     // Assert 
     Assert.NotNull (response); 
     Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); 
     Assert.AreEqual(response.Response.ToDto<PlayerResponse>().Player.Id.ToString(), response.Headers.Where(x=> x.Key == HttpHeaders.Location).SingleOrDefault().Value); 
    } 
} 

当我的单元测试运行虽然base.Request。你有什么建议可以从我的单元测试中填充这个吗?

+0

语言? C# ? – Dukeling 2013-02-09 19:49:07

+0

是:)在MonoDevelop中开发。 – 2013-02-09 19:54:16

+2

添加了相应的标签。 – Dukeling 2013-02-09 19:56:11

回答

12

您像使用集成测试一样使用自托管HttpListener,但是您没有在集成测试中进行操作。

集成测试会是什么样子:

[Test] 
public void NewPlayer_Should_Return201AndLocation() 
{ 
    var client = new JsonServiceClient("http://localhost:1337/"); 
    client.LocalHttpWebResponseFilter = httpRes => { 
     //Test response headers... 
    }; 

    PlayerResponse response = client.Post(new Player { ... }); 
} 

否则,如果你想要做一个单元测试,你并不需要一个APPHOST并且可以只测试PlayerService类,就像任何其他的C#类,注射所有它需要的依赖性和模拟的请求上下文。

[Test] 
public void NewPlayer_Should_Return201AndLocation() 
{ 
    var mockCtx = new Mock<IRequestContext>(); 
    mockCtx.SetupGet (f => f.AbsoluteUri).Returns("localhost:1337/player"); 

    PlayerService service = new PlayerService { 
     MyOtherDependencies = new Mock<IMyOtherDeps>().Object, 
     RequestContext = mockCtx.Object, 
    }; 

    HttpResult response = (HttpResult)service.Post(new Player { ... }); 

    //Assert stuff.. 
} 
+0

啊!我没有想到我可以像这样注入RequestContext new xService {RequestContext = mockCtx.Object}; 谢谢! – 2013-02-09 22:15:31

+0

注意:AbsoluteUri是只读的,因此SetupProperty不会像那样工作。 – 2013-02-09 22:17:29

+0

我能够设置这样的属性: mockCtx.SetupGet(f => f.AbsoluteUri).Returns(“http:// localhost:1337/player”); – 2013-02-09 22:48:47