문제

이 작업을 인터페이스로 수행하려면 코드를 다시 작성해야 합니까?아니면 더 쉬운 방법이 있나요?나는 Moq를 사용하고 있습니다

도움이 되었습니까?

해결책

내가 일반적으로하는 일은 웹 서비스 주변에 래퍼 또는 어댑터를 만들고 그냥 조롱하는 것입니다.

예를 들어:

public class ServiceAdapter: IServiceAdapter
{
    public void CallSomeWebMethod()
    {
        var someService = new MyWebService();
        someService.SomeWebMethod();
    }
}

그런 다음 서비스 어댑터를 스터브합니다.

[Test]    
public void SomeMethod_Scenario_ExpectedResult()
{
    var adapterMock = new Mock<IServiceAdapter>();
    //do your test
}

다른 팁

최근에 단위 테스트와 조롱에 대한 몇 가지 답변을 작성했습니다.나는 다른 곳에서 무엇을 스스로에게 물어보는 것이 중요하다고 썼습니다. 정확히 테스트 중이신가요?귀하의 특정 상황과 관련하여 대답은 "내 WebService가 노출하는 비즈니스 논리를 테스트하고 있습니다"이기를 바랍니다. ~ 아니다 "WebService를 테스트 중입니다." - 차이점이 있습니다.


당신의 우려 사항이 있다면 서버 측

일반적으로 WebServices를 테스트할 필요는 없습니다.MS는 이미 그렇게 했습니다.수백만 명의 사람들이 그렇게 했습니다.전송 계층, 프로토콜, WebService 정의를 테스트하는 것은 시간 낭비입니다.

당신은 당신의 목표를 설정해야합니다 비즈니스 로직.이를 수행하는 가장 좋은 방법은 다음과 같습니다. 분리된 WebService의 비즈니스 로직.다음을 고려하세요

public class MyWebSevice : System.Web.Services.WebService
{
    private AuthenticationService _auth = new AuthenticationService ();
    private int _count = 0;
    [WebMethod]
    public string DoSomething ()
    {
        // embedded business logic, bad bad bad
        if (_auth.Authenticate ())
        {
            _count++;
        }
        return count.ToString ();
    }
}

WebService를 직접 호출하지 않고는 해당 논리를 테스트할 방법이 없습니다.당신이 정말로 원하는 것은

public class MyService 
{
    // keeners will realise this too should be injected
    // as a dependency, but just cut and pasted to demonstrate
    // isolation
    private AuthenticationService _auth = new AuthenticationService ();
    private int _count = 0;
    public string DoSomething ()
    {
        if (_auth.Authenticate ())
        {
            _count++;
        }
        return count.ToString ();
    }
}

프로덕션에서

// this web service is now a consumer of a business class,
// no embedded logic, so does not require direct testing
public class MyWebSevice : System.Web.Services.WebService
{
    private readonly MyService _service = new MyService ();

    [WebMethod]
    public string DoSomething ()
    {
        _service.DoSomething ();
    }
}

테스트 중

// test business logic without web service! yay!
[Test]
public void Test_DoSomething ()
{
    MyService service = new MyService ();
    string actual = service.DoSomething ();
    // verify results
}

[AuthenticationService 멤버와 같은] 종속성을 관리하는 것은 별도의 문제입니다.그러나 WebMethod를 만드는 것은 간단한 통과 적절한 기본 비즈니스 클래스에 접근하고 그 클래스에서 로직을 완전히 제거하면 일반적인 WebService 구현의 연결이 아닌 "실제" 사용자 코드를 대상으로 지정할 수 있습니다.


당신의 우려 사항이 있다면 고객 입장에서

비즈니스 구성 요소가 있습니다. 부름 웹 서비스이며 단위 테스트용 클라이언트를 만들고 싶지 않다는 데 동의합니다.

public partial class MyWebService :
    System.Web.Services.Protocols.SoapHttpClientProtocol 
{
    ...
    public string DoSomething () { ... }
}

public class MyClient
{
    public void CallService ()
    {
        MyWebService client = new MyWebService ();
        client.DoSomething ();
    }
}

여기에는 종속성 문제가 있습니다. 즉, WebService를 인스턴스화하고 호스팅하지 않으면 MyClient.CallService를 테스트할 수 없습니다.특히 해당 원격 서비스를 소유하거나 호스팅하지 않는 경우 당황스럽습니다.이 경우 그렇습니다. 인터페이스에 대해 작성해야 합니다. 다시 한 번 비즈니스 로직을 분리하고 격리해야 합니다.

public interface IMyWebService
{
    string DoSomething ();
}

public class MyWebServiceWrapper : IMyWebService
{
    public string DoSomething () 
    {
        MyWebService client = new MyWebService ();
        client.DoSomething ();
    }
}

public class MyClient
{
    private readonly IMyWebService _client = null;
    public MyClient () : this (new MyWebServiceWrapper ()) { }
    public MyClient (IMyWebService client)
    {
        _client = client;
    }
    public void CallService ()
    {
        _client.DoSomething ();
    }
}

테스트 중

[Test]
public void Test_CallService ()
{
    IMyWebService mockService = null;
    // instantiate mock with expectations
    MyClient client = new MyClient (mockService);
    client.CallService ();
    // verify results
}

일반적으로 클래스의 종속성이 in-proc 서비스인 경우 종속성 주입(DI) 또는 제어 반전(IoC)과 같은 패턴을 적용할지 결정하는 것은 귀하에게 달려 있습니다. 설계.그러나 클래스의 종속성이 있는 경우 프로세스 경계를 ​​넘어, 예를 들어 Database 또는 WebService에서는 위에서 했던 것처럼 이러한 패턴을 적용하는 것이 좋습니다.

실제로 이것은 단지 오래된 인터페이스 개발일 뿐입니다.아마 당신은 그것이 어떻게 성과를 거두는지 이미 알고 있을 것입니다.

:)

이것에 대해 블로그를 작성했습니다 옛날에. 기본적으로 부분 클래스와 약간의 노력 (웹 서비스 변경 빈도에 따라 자동화 또는 매뉴얼)을 사용합니다. 웹 서비스 프록시 클래스가 인터페이스를 구현할 수 있습니다. 그런 다음 정상적으로 조롱 할 수 있습니다.

쉬운 방법이 있습니다. 예를 들어 DBSERVICE라는 이름의 WebService 클래스가있는 경우 먼저 인터페이스를 작성하고 (예 : Iservice)이 인터페이스를 사용한 다음 프로젝트에 클래스를 추가하고 다음을 수행하십시오.

public partial class DbService:IService {

}

웹 서비스 때문에이 구현을 사용하는 부분 클래스이기 때문에 클래스를 비워 두십시오. (이전에

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top