2013-02-20 31 views
5

Tôi đang sử dụng ServiceStack/StructureMap/Moq. Dịch vụ thực hiện cuộc gọi đến Session, là loại ServiceStack.CacheAccess.ISession. Đối với đơn vị xét nghiệm, tôi đã tạo ra một đối tượng Mock sử dụng Moq, và thêm nó vào cấu hình StructureMap:Làm thế nào để bạn giả lập ServiceStack ISession bằng cách sử dụng Moq và StructureMap?

protected Mock<ISession> sessionMock = new Mock<ISession>(); 
ObjectFactory.Configure(
    cfg => 
     { 
      cfg.For<ISession>().Use(sessionMock.Object); 

Tuy nhiên, tôi không ngạc nhiên khi đối tượng Session là null - Tôi chắc chắn rằng tôi sẽ đi ra một bước. Tôi cần phải làm gì khác để điền thuộc tính Phiên của tôi với đối tượng giả?

[EDIT] Đây là một trường hợp thử nghiệm đơn giản

Mã để kiểm tra. Đơn giản yêu cầu/dịch vụ

[Route("getKey/{key}")] 
public class MyRequest:IReturn<string> 
{ 
    public string Key { get; set; } 
} 

public class MyService:Service 
{ 
    public string Get(MyRequest request) 
    { 
     return (string) Session[request.Key]; 
    } 
} 

Lớp kiểm tra cơ sở và các lớp MockSession

// test base class 
public abstract class MyTestBase : TestBase 
{ 
    protected IRestClient Client { get; set; } 

    protected override void Configure(Container container) 
    { 
     // this code is never reached under any of my scenarios below 
     container.Adapter = new StructureMapContainerAdapter(); 
     ObjectFactory.Initialize(
      cfg => 
       { 
        cfg.For<ISession>().Singleton().Use<MockSession>(); 
       }); 
    } 
} 

public class MockSession : ISession 
{ 
    private Dictionary<string, object> m_SessionStorage = new Dictionary<string, object>(); 

    public void Set<T>(string key, T value) 
    { 
     m_SessionStorage[key] = value; 
    } 

    public T Get<T>(string key) 
    { 
     return (T)m_SessionStorage[key]; 
    } 

    public object this[string key] 
    { 
     get { return m_SessionStorage[key]; } 
     set { m_SessionStorage[key] = value; } 
    } 
} 

Và bài kiểm tra. Xem bình luận cho nơi tôi thấy thất bại. Tôi đã không thực sự mong đợi các phiên bản 1 & 2 để làm việc, nhưng hy vọng phiên bản 3 sẽ.

[TestFixture] 
public class When_getting_a_session_value:MyTestBase 
{ 
    [Test] 
    public void Test_version_1() 
    { 
     var session = ObjectFactory.GetInstance<MockSession>(); 
     session["key1"] = "Test"; 
     var request = new MyRequest {Key = "key1"}; 
     var client = new MyService(); // generally works fine, except for things like Session 
     var result = client.Get(request); // throws NRE inside MyService 
     result.ShouldEqual("Test"); 
    } 

    [Test] 
    public void Test_version_2() 
    { 
     var session = ObjectFactory.GetInstance<MockSession>(); 
     session["key1"] = "Test"; 
     var request = new MyRequest {Key = "key1"}; 
     var client = ObjectFactory.GetInstance<MyService>(); 
     var result = client.Get(request); // throws NRE inside MyService 
     result.ShouldEqual("Test"); 
    } 
    [Test] 
    public void Test_version_3() 
    { 
     var session = ObjectFactory.GetInstance<MockSession>(); 
     session["key1"] = "Test"; 
     var request = new MyRequest {Key = "key1"}; 
     var client = CreateNewRestClient(); 
     var result = client.Get(request); // throws NotImplementedException here 
     result.ShouldEqual("Test"); 
    } 
} 
+0

tôi nghĩ rằng đó là bởi vì tôi không có adapter StructureMap được cấu hình đúng, khi kiểm tra đơn vị. Bạn không chắc chắn cách thực hiện điều đó ... –

+0

Bạn có thể hiển thị tất cả mã cho thử nghiệm không? nghĩa là chúng tôi có thể xem bạn đang gọi dịch vụ như thế nào? – mythz

+0

Đã thêm mã hiển thị sự cố và cách tôi đã cố gắng giải quyết vấn đề. –

Trả lời

7

Có vẻ như bạn đang cố gắng tạo các bài kiểm tra đơn vị, nhưng bạn đang sử dụng một AppHost như bạn đã làm một bài kiểm tra Tích hợp. Xem số previous answer for differences between the twodocs on Testing này.

Bạn có thể thử các phiên bằng cách đăng ký một thể hiện trong Request.Items["__session"], ví dụ:

[Test] 
public void Can_mock_IntegrationTest_Session_with_Request() 
{ 
    using (new BasicAppHost(typeof(MyService).Assembly).Init()) 
    { 
     var req = new MockHttpRequest(); 
     req.Items[SessionFeature.RequestItemsSessionKey] = 
      new AuthUserSession { 
       UserName = "Mocked", 
      }; 

     using (var service = HostContext.ResolveService<MyService>(req)) 
     { 
      Assert.That(service.GetSession().UserName, Is.EqualTo("Mocked")); 
     } 
    } 
} 

Nếu không, nếu bạn thiết lập AppHost.TestMode=true ServiceStack sẽ trả lại IAuthSession đó là đăng ký tại IOC của bạn, ví dụ:

[Test] 
public void Can_mock_UnitTest_Session_with_IOC() 
{ 
    var appHost = new BasicAppHost 
    { 
     TestMode = true, 
     ConfigureContainer = container => 
     { 
      container.Register<IAuthSession>(c => new AuthUserSession { 
       UserName = "Mocked", 
      }); 
     } 
    }.Init(); 

    var service = new MyService { 
     Request = new MockHttpRequest() 
    }; 
    Assert.That(service.GetSession().UserName, Is.EqualTo("Mocked")); 

    appHost.Dispose(); 
} 
+0

Cảm ơn bạn đã trả lời! Tôi đã quá tập trung vào suy nghĩ tôi * đã * để tạo ra các dịch vụ bằng cách sử dụng một trong những phương pháp SS tôi đã không nhìn vào điền thủ công ISessionFactory. –

+0

np :) ServiceStack là khá nhiều ràng buộc cùng với các lớp học đơn giản sạch sẽ và giao diện, do đó, hầu hết thời gian điều dễ nhất sẽ làm việc :) – mythz

+0

Làm việc tuyệt vời, quá! Thay đổi nó một cách oonly một chút để làm việc với StructureMap. –