2009-05-14 2 views
2

프록시 및 호스트 이름과 모든 종류의 것들을 확인한 후 URL 문자열을 만드는 정적 메서드를 테스트하고 있습니다. 이 메서드는 내부적으로 정적 플래그 System.Net.Sockets.Socket.OSSupportsIPv6에 의존합니다. 정적이기 때문에이 종속성을 조롱 할 수 없습니다.기계 별 동작에 대한 단위 테스트는 어떻게합니까?

편집 : (이것은 많이 단순화되었습니다 ... 참/거짓을 허용하는 플래그로 메소드의 구조를 수정할 수 없습니다).

XP 개발 컴퓨터에서 문제의 메서드는 예측 가능한 문자열 결과 (이 경우 http://hostname/ ....)를 반환합니다. IPv6를 지원하는 빌드 서버는 완전히 다른 결과를 반환합니다 (이는 내게 http://192.168.0.1:80/...과 같은 것을 제공합니다). 이유를 묻지 마십시오. 요점은 운영 체제 종속성에 따라 다른 두 가지 출력 유형이 있다는 것입니다.

테스트에서 반환 된 호스트 이름이나 IP 주소가 유효한지 확인해야합니다. 출력물을 쉽게 확인할 수 있습니다. 문제는 테스트를 실행할 시스템에 따라 가능한 출력 중 하나만 가져올 수 있다는 것입니다.

이 경우 테스트를 작성하는 가장 좋은 방법은 무엇입니까? 플래그를 검사하고 두 개의 다른 출력을 찾는 if 문을 테스트에 넣습니까? 테스트가 다르게 행동 환경에 따라됩니다

  1. 때문에 당신이 알고 할 필요가 있기 때문에,

  2. 나는 기본적으로 방법으로 시험 을 결합하고있어에서 실행의 나에게 스케치 보인다 방법의 내부는 두 가지 경우를 설정합니다.

각 환경마다 하나씩 잘못된 환경에있을 때 통과하는 두 가지 테스트를 설정합니까? 어떤 종류의 결과가 나오는지를 구분할 수있는 복잡한 정규 표현식을 작성하고 그것을 검증하기 위해 if/else 논리를 더 사용합니까?

어떤 제안이 도움이 될 것입니다!

답변

1

추상 인터페이스 뒤에 정적 메서드를 숨길 수 있습니까?

interface ISupportIPv6 
{ 
    bool supported { get; } 
} 

//class for unit testing 
class TestSupportsIPv6 : ISupportIPv6 
{ 
    public bool supported { get { return true; } } 
} 

//another class for more unit testing 
class TestDoesNotSupportIPv6 : ISupportIPv6 
{ 
    public bool supported { get { return false; } } 
} 

//class for real life (not unit testing) 
class OsSupportsIPv6 : ISupportIPv6 
{ 
    public bool supported { get { 
    return System.Net.Sockets.Socket.OSSupportsIPv6; } } 
} 
0

당신이 왜 조롱 할 수 없는지 저는 이해가 가지 않습니다. 메소드에는 bool SupportsIPv6 매개 변수가 필요하며 실제 코드에는 System.Net.Sockets.Socket.OSSupportsIPv6을 전달하십시오. 그런 다음 매개 변수를 true 및 false로 설정하여 메서드를 테스트하고 true 및 false 경우에 올바른 형식을 지정하는지 확인합니다. Voila, 끝났어.

+0

그러면 사이트를 테스트하기가 힘들어집니다. 그게 아마도 문제가 아닐지도 몰라 ... –

+0

그건 분명히 이상적 일거야. 나는 실제로 그것을 단순화 시켰습니다. 몇 가지 외부 호출이있었습니다. 의존하는 플래그는 실제로 제어 할 수없는 .dll에 있습니다. – womp

+0

나는 본다. 그럼, 수치 스럽네요. – mquander

0

유용한 단위 테스트를 만드는 것은 너무 어렵습니다. 나는이 사건 중 하나라고 확신하지는 않지만 기억할 만하다.

그렇다면 "유효한"의미를 정의하시오. 당신은 확실히 그것이 잘 형성되었는지 테스트 할 수 있습니다 : [0-9] {1,3}은 그것을위한 정규식의 시작입니다.

ICMP 에코 패킷 (또는 ping (8))을 사용하여 연결할 수 있는지 테스트 할 수 있습니다.

"유효한"것이 무엇을 의미하는지 정의 할 수 있다면 단위 테스트를 시작해야합니다.

+0

확실한 좋은 지적입니다. 이 경우 질문은 테스트 구조에 관한 것입니다. 출력이 유효한 시점을 확실히 알고 있습니다. 그러나 테스트를 실행하는 위치에 따라 출력 중 하나만 테스트 할 수 있습니다. – womp

2

중간을 소개하여 전화를 가짜로 만들 수 있습니다.예를 들면 다음과 같습니다.

public static class NetworkUtils 
{ 
    private static bool? forcedIPv6Support; 

    /// <summary> 
    /// Use this instead of Socket.OSSupportsIPv6 to 
    /// allow for testing on different operating systems. 
    /// </summary> 
    public static SupportsIPv6 
    { 
     get { return forcedIPv6Support ?? Socket.OSSupportsIPv6; } 
    } 

    /// <summary>Only use in testing!</summary> 
    public static void ForceIPv6Support(bool? value) 
    { 
     forcedIPv6Support = value; 
    } 
} 

당신이 필요로하는 것을 할 수 있습니다.

ChrisW's answer과 비슷하지만 인터페이스를 사용합니다. 일반적으로 나는 인터페이스 솔루션에 대한 팬 일 것입니다.하지만 생산 코드와 구성을 더욱 복잡하게 만드는 것처럼 느낍니다. 내 솔루션은 확실히 "순전 한"것이 아니라 사실상 더 실용적인 것입니다. 내가 너를 판단하게 할 것이다 :)

+0

솔루션이 더 짧아서 ("엔터티를 필요 이상으로 배증해서는 안됩니다.") 더 나은 솔루션입니다. – ChrisW

+0

둘 다 내가 찌르는 코드를 아주 많이 망칠 필요없이 구축 할 수 있다는 훌륭한 제안입니다. – womp

1

인터페이스를 구현하는 별도의 클래스에서 변경할 수있는 모든 환경 설정을 래핑 할 수있다. 이것은 당신이 작성한 정적 메소드에 전달 될 수 있으며, 다양한 메소드가 필요할 때 인터페이스에 대해 콜백 할 것입니다.

이렇게하면 테스트 할 때 환경 설정을 표준화하여보고있는 문제를 방지 할 수 있습니다. 또한 다른 조건을 테스트하기 위해 설정을 변경할 수 있습니다.

그러면 정적 방법이됩니다.

public static void DoSomething(IEnvironment environment) 
{ 
    if(environment.SupportsIPV6) 
    { 
     ... 
    } 
} 

그런 다음 사용의 실제 설정을 얻기 위해 정적 System.Net 방법에 대해 호출 IEnvironment의 구현하지만, 알려진 값을 테스트하기위한 모의 구현을 제공합니다.

정적 메서드에 인터페이스를 전달하지 않으려면이 인터페이스로 호출되는 단일 패턴을 사용하여 개체를 구현할 수 있습니다. 정적 메소드를 사용하면 싱글 톤을 사용하여 현재 인터페이스가 무엇이든 액세스 할 수 있습니다.하지만이 메소드는 약간 지저분하므로 전 (前) 유형으로 이동할 것입니다.

예.

public Environment : IEnvironment 
{ 
    private static IEnvironment current = new Environment(); 
    public static IEnvironment Current 
    { 
    get { return current; } 
    set { current = value; } 
    } 

    public bool SupportsIPV6 
    { 
    return System.Net..... 
    } 
} 

다음을 사용하여 정적 방법으로 호출하십시오.

public static void DoSomething(IEnvironemnt environment) 
{ 
    if(Environment.Current.SupportsIPV6) 
    { 
     ... 
    } 
} 

그리고 당신은 당신이 그와 같은 싱글 어떤 멀티 스레딩을하고 있다면 조심해야 할 것입니다하지만 당신은

Environment.Current = new MockedEnvironment(); 

를 통해 테스트에서 변경할 수 있습니다.

관련 문제