2014-01-31 15 views
2

我有一個使用WCF客戶端代理的facade類。爲了防止IDispose的WCF代理客戶端出現問題(WCF中的bug,仍未被MS修復),我創建了一個通用的代理服務來完成調用WCF服務的基本工作。如何配置Moq使用通用動作<T>

我想用Moq單元測試門面,我有一個問題如何使用Moq在單元測試中進入特定的調用。單元測試要驗證的進程管理器調用做只有一次,但代碼不「使用」方法中的流動....


(編輯) 爲了完整這裏是,解決了該問題的部分:

public AuthenticationFacade CreateSut() 
     { 
      ProcessManager = new Mock<IProcessManager>().Object; 
      SessionWrapper = new Mock<ISessionWrapper>().Object; 

      AuthenticationClientProxy = new Mock<Action<IAuthentication>>().Object; 

      var authenticationProxyServiceMock = new Mock<IProxyService<IAuthentication>>(); 

      Mock<IAuthentication> mockAuthentication = new Mock<IAuthentication>(); 
      authenticationProxyServiceMock.Setup(aps => aps.Use(It.IsAny<Action<IAuthentication>>())) 
          .Callback<Action<IAuthentication>>(ac => ac(mockAuthentication.Object)); 

      AuthenticationProxyService = authenticationProxyServiceMock.Object; 

      return new AuthenticationFacade(ProcessManager, SessionWrapper, AuthenticationProxyService); 
     } 

(基準碼)

代碼部分1:

using System; 

    namespace Progis.Kim 
    { 
     public interface IProxyService<T> 
     { 
      void Use(Action<T> action); 
     } 
    } 

代碼第2部分:

/// <summary> 
    /// Helper class to fix the WCF Client Proxy usage bug with IDispose. 
    /// Check: http://benmccallum.wordpress.com/2011/08/27/wcf-web-service-wrapper-closing-disposing-and-aborting-best-practices/ 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    public class ProxyService<T> : IProxyService<T> 
    { 
     public void Use(Action<T> action) 
     { 
      <cut>.... 
     } 
    } 

代碼第3部分:

public class AuthenticationFacade : IAuthenticationFacade 
    { 
     private readonly IProcessManager processManager; 
     private readonly ISessionWrapper sessionWrapper; 
     private readonly IProxyService<IAuthentication> authenticationProxyService; 

     public AuthenticationFacade(
      IProcessManager processManager, 
      ISessionWrapper sessionWrapper, 
      IProxyService<IAuthentication> authenticationProxyService) 
     { 
      this.processManager = processManager; 
      this.sessionWrapper = sessionWrapper; 
      this.authenticationProxyService = authenticationProxyService; 
     } 

     public bool ValidateGebruiker(string gebruikernaam, string wachtwoord) 
     { 
      bool authenticated = false; 


      authenticationProxyService.Use(client => 
      { 
       var sessionId = processManager.GetSessionId(); 

        authenticated = client.ValidateGebruiker(
        sessionId, 
        gebruikernaam, 
        wachtwoord); 
      }); 

      return authenticated; 
     } 

代碼部分4:

public class AuthenticationFacadeFixture 
    { 
     public IProcessManager ProcessManager { get; set; } 

     public ISessionWrapper SessionWrapper { get; set; } 

     public IProxyService<IAuthentication> AuthenticationProxyService { get; set; } 

     public AuthenticationFacade CreateSut() 
     { 
      ProcessManager = new Mock<IProcessManager>().Object; 
      SessionWrapper = new Mock<ISessionWrapper>().Object; 
      AuthenticationProxyService = new Mock<IProxyService<IAuthentication>>().Object; 

      return new AuthenticationFacade(ProcessManager, SessionWrapper, AuthenticationProxyService); 
     } 
    } 

代碼部分5:

public static class MockExtensions 
    { 
     public static Mock<T> AsMock<T>(this T obj) where T : class 
     { 
      return Mock.Get(obj); 
     } 
    } 

代碼第6部分(單元測試):

[TestMethod] 
     public void ValidateGebruiker_calls_processmanager_getsessionid_once() 
     { 
      // Arrange 
      var fixture = new AuthenticationFacadeFixture(); 
      var sut = fixture.CreateSut(); 

      var validUserPass = CreateValidGebruikersnaamWachtwoord(); 

      // Act 
      sut.ValidateGebruiker(validUserPass.Gebruikersnaam, validUserPass.Wachtwoord); 

      // Assert 
      fixture.ProcessManager.AsMock().Verify(pm => pm.GetSessionId(), Times.Once()); 
     } 

回答

1

你已經忽略你的起訂量設置代碼,這使得這個有點困難,但我相信它看起來是這樣的:

AuthenticationProxyService.Setup(a => a.Use(It.IsAny<Action<IAuthentication>>())); 

如果是這樣,你可以做到以下幾點:

// Not sure if you have this mock already, this is the "client" variable 
// in your Use method action 
Mock<IAuthentication> mockAuthentication = mockRepository.Create<IAuthentication>(); 

AuthenticationProxyService.Setup(a => a.Use(It.IsAny<Action<IAuthentication>>())) 
          .Callback<Action<IAuthentication>>(a => a(mockAuthentication.Object)); 

Callback方法從設置接收參數(一個Action<IAuthentication>),在這種情況下,它是ValidateGebruiker中的代碼,只需用模擬的IAuthentication對象調用它即可(如果您尚未使用該對象,則需要使用Setup)。

+0

工程就像一個魅力!謝謝! –