생성자에 매개 변수가있을 때 Moq로 객체 모의


94

moq를 사용하여 조롱하려는 개체가 있습니다. 객체의 생성자에는 필수 매개 변수가 있습니다.

public class CustomerSyncEngine {
    public CustomerSyncEngine(ILoggingProvider loggingProvider, 
                              ICrmProvider crmProvider, 
                              ICacheProvider cacheProvider) { ... }
}

이제 moq의 v3 "setup"또는 v4 "Mock.Of"구문을 사용하여이 개체에 대한 모의를 만들려고합니다. 그러나 이것을 알아낼 수 없습니다. 제가 시도하고있는 모든 것이 유효성을 검사하지 않습니다. 여기 내가 지금까지 가지고있는 것이 있지만 마지막 줄은 모의가 아닌 실제 개체를 제공하는 것입니다. 이 작업을 수행하는 이유는 확인하려는 CustomerSyncEngine에 메서드가 호출되고 있기 때문입니다.

// setup
var mockCrm = Mock.Of<ICrmProvider>(x => x.GetPickLists() == crmPickLists);
var mockCache = Mock.Of<ICacheProvider>(x => x.GetPickLists() == cachePickLists);
var mockLogger = Mock.Of<ILoggingProvider>();

// need to mock the following, not create a real class like this...
var syncEngine = new CustomerSyncEngine(mockLogger, mockCrm, mockCache);

호출되고 있는지 확인하려는 샘플 메서드를 제공 할 수 있습니까?
Ciaran

4
따라서 인터페이스가 아닌 클래스에 대한 종속성이 있으면 해당 종속성까지 조롱해야합니다. 이것은 재귀 적으로 내려갑니다. 결국에는 코드에 인터페이스가 필요하지 않더라도 코드를 테스트 할 수 있도록 일부 인터페이스를 사용해야합니다. 나는 너무 많은 인터페이스가 구체적인 클래스를 조롱하는 것보다 더 큰 냄새라고 생각합니다 ...
Tarion

답변:


34

마지막 줄은 CustomerSyncEngine을 조롱하는 것이 아니라 new 키워드를 사용하고 있기 때문에 실제 인스턴스를 제공하는 것입니다.

당신은 사용해야합니다 Mock.Of<CustomerSyncEngine>()

Mocking Concrete 유형의 유일한 문제는 Moq에 공용 기본 생성자 (매개 변수 없음)가 필요하거나 생성자 arg 사양으로 Moq를 만들어야한다는 것입니다. http://www.mockobjects.com/2007/04/test-smell-mocking-concrete-classes.html

가장 좋은 방법은 클래스를 마우스 오른쪽 버튼으로 클릭하고 인터페이스 추출을 선택하는 것입니다.


3
문제와 관련하여 대안은 AutoMocking 컨테이너를 사용하는 것입니다. 내가 가장 좋아하는 것은 Machine.Fakes와 Machine.Specifications는 자동 모의 컨테이너를 사용하면 더 작은 표면 영역을 테스트하기가 더 쉽습니다. Andrew 가 기존의 모의 구현 CustomerSyncEngine에서만 사용 하는 방법을 ICrmProvider3 개의 인터페이스 모두에 제공해야하는 반면 autmocking 컨테이너는 하나만 제공 할 수 있는 방법을 테스트해야한다고 가정 합니다.
Chris Marisic 2014 년

74

마지막 줄을

var syncEngine = new Mock<CustomerSyncEngine>(mockLogger, mockCrm, mockCache).Object;

그리고 그것은 작동합니다


3
이 의견이 내 답변에 어떻게 적용되는지 잘 모르시겠습니까?
Suhas

2
이것은 mockLogger와 다른 사람들이 Object 속성이 없다는 예외를 던지므로 컴파일 오류가 발생하기 때문에
Justin Pihony

2
OP는 Mock.Of <T> ()를 사용하여 로거, crm 및 캐시 유형의 모의를 만들기 때문에 반환 된 개체는 Mock <T>가 아닌 T로 반환됩니다. 따라서 mockLogger.Object 등은 CustomerSyncEngine의 Mock에 제공 할 때 필요하지 않으며 @JustinPihony가 언급했듯이 디자인 타임 오류를 표시해야합니다.
Josh Gust

1
@suhas해야하지 자신의 BEnew Mock<CustomerSyncEngine>(new object[]{mockLogger, mockCrm, mockCache}).Object;
GiriB

@GiriB는 필요하지 않지만 Params로 모의가 정의되어 있으므로 가능합니다. public Mock (params object [] args)
Jiří Herník
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.