2010-01-03 5 views
2

Webforms Page 객체 인 에 ClientScriptManager 클래스를 모의하고 싶습니다. 그러나 내가 할 수없는 것처럼 보입니다. 내가 봉인 할 수없는 오류가 발생합니다. 수업.Rhino Mock으로 ClientScriptManager의 모의 객체 만들기

MockRepository mocks = new MockRepository() 

Page page = mocks.PartialMock<Page>(); 

var clientScript = mocks.PartialMock<ClientScriptManager>(); //error here 

SetupResult.For(page.ClientScript).Return(clientScript); 

clientscriptmanager를 조롱하는 방법에 대한 조언을 보내 주시면 감사하겠습니다.

답변

4

발견 한 것처럼 대부분의 조롱 라이브러리를 사용하여 봉인 된 유형을 조롱 할 수 없습니다. 이 이유 중 하나는 파생 된 유형을 작성하여 많은 모의 라이브러리가 작동하지만 클래스가 봉인 된 경우 파생 클래스에서 파생 될 수 없다는 것입니다.

Microsoft에서 내부적으로 수행 한 작업은 손으로 작성한 IClientScriptManager 인터페이스를 사용하고 해당 인터페이스를 구현하는 ClientScriptManagerWrapper을 사용하고 모든 호출을 실제 ClientScriptManager에 위임한다는 것입니다.

그런 다음 ClientScriptManager을 사용해야하는 유형은 IClientScriptManager으로 변경됩니다. 런타임에 우리는 ClientScriptManagerWrapper을 생성하고 (실제 ClientScriptManager을 전달합니다). 테스트 시간에 모의 객체 라이브러리를 사용하여 모의 객체 IClientScriptManager을 만들고이를 대신 사용합니다.

public class SomeClassThatNeedsClientScriptManager { 
    private IClientScriptManager _iClientScriptManager; 

    public IClientScriptManager IClientScriptManager { 
     get { 
      if (_iClientScriptManager == null) { 
       _iClientScriptManager = new ClientScriptManagerWrapper(Page.ClientScriptManager); 
      } 
      return _iClientScriptManager; 
     } 
     set { 
      _iClientScriptManager = value; 
     } 
    } 

    public void SomeMethodThatUsesClientScriptManager() { 
     IClientScriptManager.RegisterClientScriptBlock(typeof(Whatever), "key", "alert('hello')"); 
    } 
} 

public interface IClientScriptManager { 
    void RegisterClientScriptBlock(Type type, string key, string script); 
} 

public class ClientScriptManagerWrapper : IClientScriptManager { 
    private readonly ClientScriptManager _clientScriptManager; 

    public ClientScriptManagerWrapper(ClientScriptManager clientScriptManager) { 
     if (clientScriptManager == null) { 
      throw new ArgumentNullException("clientScriptManager"); 
     } 
     _clientScriptManager = clientScriptManager; 
    } 

    public void RegisterClientScriptBlock(Type type, string key, string script) { 
     _clientScriptManager.RegisterClientScriptBlock(type, key, script); 
    } 
} 

당신은 다음 IClientScriptManager 인터페이스를 수정할 수 있고, ClientScriptManagerWrapper는 당신이 필요로하는 어떤 방법을 가지고 :

그리고 여기에는 코드 샘플입니다.

+0

내부적으로 너무 나쁘다. 더 많은 프레임 워크 유형이 공용 인터페이스와 래퍼를 구현하여 테스트 가능한 코드가 더 적은 레이어와 상호 운용 될 수 있도록하고 싶습니다. 하지만 이것이 우리가 래퍼를 포장하는 이유입니다. :) – maxwellb

+0

@maxwellb 실제로 (ASP.NET 공간에서) 새로운 프레임 워크의 대부분을 보면 훨씬 많은 인터페이스와 추상 기본 클래스를 볼 수 있습니다. 예를 들어, MVC, Web API 및 SignalR은 모두 인터페이스를 많이 사용하므로 이러한 유형의 시나리오를 훨씬 쉽게 구현할 수 있습니다. – Eilon