developer tip

실드 클래스를 어떻게 조롱합니까?

optionbox 2020. 12. 2. 08:30
반응형

실드 클래스를 어떻게 조롱합니까?


봉인 된 수업을 조롱 하는 것은 상당히 고통 스러울 수 있습니다. 나는 현재 이것을 처리하기 위해 어댑터 패턴선호 하지만, 뭔가 이상하게 느껴집니다.

그렇다면 봉인 된 수업을 조롱하는 가장 좋은 방법은 무엇입니까?

Java 답변은 환영 이상 입니다. 사실 저는 Java 커뮤니티가이 문제를 더 오래 다루고 있으며 많은 것을 제공 할 것으로 예상합니다.

그러나 다음은 .NET 의견 중 일부입니다.


일반적인 경험 법칙은 조롱해야하는 객체도 공통 인터페이스를 가져야한다는 것입니다. 나는 이것이 디자인 측면에서 옳고 테스트를 훨씬 쉽게 만든다고 생각합니다 (그리고 일반적으로 TDD를 수행하면 얻는 것입니다). 이에 대한 자세한 내용은 Google Testing Blog 최신 게시물 에서 읽을 수 있습니다 (9 번 항목 참조).

또한, 저는 지난 4 년 동안 주로 Java로 작업 해 왔으며 최종 (밀봉 된) 클래스를 만든 횟수를 한 손으로 믿을 수 있다고 말할 수 있습니다. 여기에서 또 다른 규칙은 기본적으로 클래스를 봉인하는 것과는 반대로 항상 클래스를 봉인 할 좋은 이유가 있어야한다는 것입니다.


.NET의 경우 프로파일 링 API를 사용하고 거의 모든 호출에 연결할 수있는 TypeMock 과 같은 것을 사용할 수 있습니다.


나는 믿고 , 마이크로 소프트 리서치에서, 당신은 그렇게 할 수 있습니다. 두더지 페이지에서 :

두더지는 봉인 된 유형의 비가 상 / 정적 방법을 포함하여 모든 .NET 방법을 우회하는 데 사용할 수 있습니다.

업데이트 : 다가오는 VS 11 릴리스에는 Moles를 대체하도록 설계된 "Fakes"라는 새로운 프레임 워크가 있습니다.

Visual Studio 11Fakes Framework는 차세대 Moles & Stub이며 결국이를 대체 할 것입니다. 그러나 가짜는 두더지와 다르므로 두더지에서 가짜로 이동하려면 코드를 약간 수정해야합니다. 이 마이그레이션에 대한 가이드는 나중에 사용할 수 있습니다.

요구 사항 : Visual Studio 11 Ultimate, .NET 4.5


TypeMock의 문제점은 잘못된 디자인을 용서한다는 것입니다. 이제 다른 사람의 나쁜 디자인이 숨어있는 경우가 많다는 것을 알고 있지만 개발 프로세스에이를 허용하면 자신의 잘못된 디자인을 쉽게 허용 할 수 있습니다.

모킹 프레임 워크를 사용하려는 경우 기존 프레임 워크 (예 : Moq)를 사용하고 모의 할 수없는 항목 주위에 격리 레이어를 만들고 대신 격리 레이어를 모의해야합니다.


나는 거의 항상 내 코드 내에서 외부 클래스에 대한 종속성을 피합니다. 대신, 나는 그들과 대화하기 위해 어댑터 / 브리지를 훨씬 더 많이 사용합니다. 그런 식으로, 나는 내 의미를 다루고 있으며 번역의 고통은 하나의 클래스에서 분리됩니다.

또한 장기적으로 내 종속성을 쉽게 전환 할 수 있습니다.


나는 최근 에이 문제를 발견했으며 웹을 읽거나 검색 한 후에 위에서 언급 한 다른 도구를 사용하는 것 외에는 쉬운 방법이없는 것 같습니다. 또는 내가 한 것처럼 처리하는 것이 조잡합니다.

  • 생성자를 호출하지 않고 봉인 된 클래스의 인스턴스를 만듭니다.
  • System.Runtime.Serialization.FormatterServices.GetUninitializedObject (instanceType);

  • 리플렉션을 통해 속성 / 필드에 값 할당

  • YourObject.GetType (). GetProperty ( "PropertyName"). SetValue (dto, newValue, null);
  • YourObject.GetType (). GetField ( "FieldName"). SetValue (dto, newValue);

나는 일반적으로 인터페이스와 어댑터 / 프록시 클래스를 생성하여 봉인 된 유형의 조롱을 용이하게합니다. 그러나 인터페이스 생성을 건너 뛰고 프록시 유형을 가상 메서드로 봉인하지 않는 실험도했습니다. 이것은 프록시가 봉인 된 클래스의 일부를 캡슐화하고 사용자가 사용하는 실제 기본 클래스 일 때 잘 작동했습니다.

이 적응이 필요한 코드를 다룰 때 인터페이스와 프록시 유형을 생성하기 위해 동일한 작업을 수행하는 데 지쳐서 작업을 자동화하는 라이브러리를 구현했습니다.

코드는 소스 코드 대신 어셈블리를 생성하고 모든 유형에서 코드 생성을 수행 할 수 있으며 많은 구성이 필요하지 않기 때문에 참조하는 기사에 제공된 샘플보다 다소 정교합니다.

자세한 내용은 이 페이지 를 참조 하십시오 .


많은 프레임 워크 클래스가 봉인되어 있기 때문에 봉인 된 클래스를 모의하는 것이 합리적입니다.

제 경우에는 우아한 예외 처리 논리를 TDD 할 수 있도록 .Net의 MessageQueue 클래스를 모의하려고합니다.

"무효 회원에 대한 잘못된 설정"에 대한 Moq의 오류를 극복하는 방법에 대한 아이디어가있는 사람이 있으면 알려주십시오.

암호:

    [TestMethod]
    public void Test()
    {
        Queue<Message> messages = new Queue<Message>();
        Action<Message> sendDelegate = msg => messages.Enqueue(msg);
        Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate =
            (v1, v2) =>
            {
                throw new Exception("Test Exception to simulate a failed queue read.");
            };

        MessageQueue mockQueue = QueueMonitorHelper.MockQueue(sendDelegate, receiveDelegate).Object;
    }
    public static Mock<MessageQueue> MockQueue
                (Action<Message> sendDelegate, Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate)
    {
        Mock<MessageQueue> mockQueue = new Mock<MessageQueue>(MockBehavior.Strict);

        Expression<Action<MessageQueue>> sendMock = (msmq) => msmq.Send(It.IsAny<Message>()); //message => messages.Enqueue(message);
        mockQueue.Setup(sendMock).Callback<Message>(sendDelegate);

        Expression<Func<MessageQueue, Message>> receiveMock = (msmq) => msmq.Receive(It.IsAny<TimeSpan>(), It.IsAny<MessageQueueTransaction>());
        mockQueue.Setup(receiveMock).Returns<TimeSpan, MessageQueueTransaction>(receiveDelegate);

        return mockQueue;
    }

현재 베타 릴리스에서만 사용할 수 있지만 새로운 Fakes 프레임 워크 ( Visual Studio 11 베타 릴리스의 일부)의 shim 기능을 염두에 둘 가치가 있다고 생각합니다 .

Shim types provide a mechanism to detour any .NET method to a user defined delegate. Shim types are code-generated by the Fakes generator, and they use delegates, which we call shim types, to specify the new method implementations. Under the hood, shim types use callbacks that were injected at runtime in the method MSIL bodies.

Personally I was looking at using this to mock the methods on sealed framework classes such as DrawingContext.


Is there a way to implement a sealed class from an interface... and mock the interface instead?

Something in me feels that having sealed classes is wrong in the first place, but that's just me :)

참고URL : https://stackoverflow.com/questions/6484/how-do-you-mock-a-sealed-class

반응형