Windows 7에서 C #을 사용하여 .NET 4.0에서 작업하고 있습니다.
mock을 사용하여 일부 방법 간의 통신을 테스트하고 싶습니다. 유일한 문제는 인터페이스를 구현하지 않고하고 싶다는 것입니다. 가능합니까?
모의 객체에 대한 많은 주제와 튜토리얼을 읽었지만 모두 클래스가 아닌 인터페이스를 모의하는 데 사용되었습니다. Rhino와 Moq 프레임 워크를 사용해 보았습니다.
Windows 7에서 C #을 사용하여 .NET 4.0에서 작업하고 있습니다.
mock을 사용하여 일부 방법 간의 통신을 테스트하고 싶습니다. 유일한 문제는 인터페이스를 구현하지 않고하고 싶다는 것입니다. 가능합니까?
모의 객체에 대한 많은 주제와 튜토리얼을 읽었지만 모두 클래스가 아닌 인터페이스를 모의하는 데 사용되었습니다. Rhino와 Moq 프레임 워크를 사용해 보았습니다.
답변:
가짜가 필요한 모든 방법을 virtual
비공개가 아닌 것으로 표시하기 만하면 됩니다. 그러면 메서드를 재정의 할 수있는 가짜를 만들 수 있습니다.
사용 new Mock<Type>
하고 매개 변수가없는 생성자가없는 경우 매개 변수를 위의 호출 인수로 전달할 수 있습니다.param Objects
대부분의 모의 프레임 워크 (Moq 및 RhinoMocks 포함)는 모의 클래스를 대신하여 프록시 클래스를 생성하고 사용자가 정의한 동작으로 가상 메서드를 재정의합니다. 이로 인해 구체적 또는 추상 클래스의 인터페이스 또는 가상 메서드 만 모의 처리 할 수 있습니다. 또한 구체적인 클래스를 모의하는 경우 모의 프레임 워크가 클래스를 인스턴스화하는 방법을 알 수 있도록 거의 항상 매개 변수없는 생성자를 제공해야합니다.
코드에서 인터페이스 생성을 싫어하는 이유는 무엇입니까?
MoQ를 사용하면 구체적인 클래스를 모의 할 수 있습니다.
var mocked = new Mock<MyConcreteClass>();
그러나이를 통해 virtual
코드 (메서드 및 속성) 를 재정의 할 수 있습니다 .
new Mock<MyConcreteClass>(param1, anotherParam, thirdParam, evenMoreParams);
그 클래스에 대한 인터페이스를 만드는 것이 더 낫다고 생각합니다. 그리고 인터페이스를 사용하여 단위 테스트를 만듭니다.
해당 클래스에 액세스 할 수없는 경우 해당 클래스에 대한 어댑터를 만들 수 있습니다.
예를 들면 :
public class RealClass
{
int DoSomething(string input)
{
// real implementation here
}
}
public interface IRealClassAdapter
{
int DoSomething(string input);
}
public class RealClassAdapter : IRealClassAdapter
{
readonly RealClass _realClass;
public RealClassAdapter() => _realClass = new RealClass();
int DoSomething(string input) => _realClass.DoSomething(input);
}
이렇게하면 IRealClassAdapter를 사용하여 클래스에 대한 모의 객체를 쉽게 만들 수 있습니다.
작동하기를 바랍니다.
표준 모의 프레임 워크는 프록시 클래스를 만듭니다. 이것이 기술적으로 인터페이스와 가상 방법으로 제한되는 이유입니다.
'정상적인'메소드도 모의하려면 프록시 생성 대신 계측과 함께 작동하는 도구가 필요합니다. 예를 들어 MS Moles와 Typemock은 그렇게 할 수 있습니다. 그러나 전자에는 끔찍한 'API'가 있고 후자는 상업적입니다.
테스트중인 클래스를 변경할 수없는 경우 제가 제안 할 수있는 유일한 옵션은 MS Fakes https://msdn.microsoft.com/en-us/library/hh549175.aspx를 사용하는 것 입니다. 그러나 MS Fakes는 Visual Studio의 일부 버전에서만 작동합니다.
인터페이스 나 모범 사례가 포함되지 않은 기존 및 레거시 프로젝트 중 하나에서 이와 같은 문제에 직면했으며 프로젝트 비즈니스의 성숙으로 인해 다시 빌드하거나 코드를 리팩토링하기가 너무 어렵습니다. 내 UnitTest 프로젝트에서 모의하려는 클래스에 대한 래퍼를 만들고 설정하고 작업하려는 모든 필요한 메서드를 포함하는 래퍼 구현 인터페이스를 만들었습니다. 이제 실제 클래스 대신 래퍼를 모의 할 수 있습니다.
예를 들면 :
가상 메소드를 포함하지 않거나 인터페이스를 구현하지 않은 테스트하려는 서비스
public class ServiceA{
public void A(){}
public String B(){}
}
moq에 래퍼
public class ServiceAWrapper : IServiceAWrapper{
public void A(){}
public String B(){}
}
래퍼 인터페이스
public interface IServiceAWrapper{
void A();
String B();
}
단위 테스트에서 이제 래퍼를 모의 할 수 있습니다.
public void A_Run_ChangeStateOfX()
{
var moq = new Mock<IServiceAWrapper>();
moq.Setup(...);
}
이것은 모범 사례가 아닐 수도 있지만 프로젝트 규칙이 이런 방식으로 강제한다면 그렇게하십시오. 또한 불필요한 래퍼 또는 어댑터로 프로젝트에 과부하가 걸리지 않도록 단위 테스트 프로젝트 또는 단위 테스트 전용 도우미 프로젝트에 모든 래퍼를 넣습니다.
업데이트 : 이 답변은 1 년이 넘었지만 올해에는 다른 솔루션으로 비슷한 시나리오가 많이 발생했습니다. 예를 들어 Microsoft Fake Framework를 사용하여 모의, 가짜 및 스텁을 만들고 인터페이스없이 개인 및 보호 된 메서드를 테스트하는 것은 매우 쉽습니다. 읽을 수 있습니다. https://docs.microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-microsoft-fakes?view=vs-2017