2013-02-20 71 views
5

我正在使用ServiceStack/StructureMap/Moq。該服務調用Session,這是類型ServiceStack.CacheAccess.ISession。單元測試,我創建使用起訂量模擬對象,並把它添加到StructureMap配置:如何使用Moq和StructureMap來模擬ServiceStack ISession?

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

不過,我並不感到驚訝,當Session對象爲空 - 我敢肯定,我離開走出一步。我還需要做什麼才能用模擬對象填充我的Session屬性?

這是一個簡單的測試場景

要測試的代碼。簡單的請求/服務

[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]; 
    } 
} 

的基礎測試類和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; } 
    } 
} 

和測試。看到我看到失敗的地方的評論。我並沒有真正期望版本1 & 2能夠正常工作,但希望版本3可以。

[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

我認爲這是因爲我沒有在單元測試時正確配置StructureMap適配器。不知道該怎麼做... – 2013-02-20 15:17:25

+0

你可以顯示所有的測試代碼?即我們可以看到您如何致電該服務? – mythz 2013-02-20 23:30:37

+0

添加了顯示問題的代碼以及我如何解決問題。 – 2013-02-21 16:10:54

回答

7

它看起來像你想創建單元測試,但像你傷口的集成測試你使用的是APPHOST。看到這個previous answer for differences between the twodocs on Testing

您可以通過在Request.Items["__session"]註冊一個實例,如嘲笑會議:

[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")); 
     } 
    } 
} 

否則,如果你設置AppHost.TestMode=true ServiceStack將返回在你的國際奧委會註冊的IAuthSession,如:

[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

感謝您的迴應!我非常專注于思考我有*使用SS方法之一創建服務,我沒有手動填寫ISessionFactory。 – 2013-02-21 21:32:22

+0

np :) ServiceStack幾乎與簡單的乾淨類和接口綁定在一起,所以大多數時候最簡單的東西都可以工作:) – mythz 2013-02-21 21:41:21

+0

工作也很棒!只需稍加改動即可使用StructureMap。 – 2013-02-21 22:05:27