Andrew Connell
Andrew Connell

Reputation: 5287

Mocking objects with Moq when constructor has parameters

I have an object I'm trying to mock using moq. The object's constructor has required parameters:

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

Now I'm trying to create the mock for this object using either moq's v3 "setup" or v4 "Mock.Of" syntax but can't figure this out... everything I'm trying isn't validating. Here's what I have so far, but the last line is giving me a real object, not the mock. The reason I'm doing this is because I have methods on the CustomerSyncEngine I want to verify are being called...

// 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);

Upvotes: 136

Views: 157723

Answers (3)

Raghu
Raghu

Reputation: 2758

The last line is giving you a real instance because you are using the new keyword, not mocking CustomerSyncEngine.

You should use Mock.Of<CustomerSyncEngine>()

The only problem with Mocking Concrete types is that Moq would need a public default constructor(with no parameters) OR you need to create the Moq with constructor arg specification.

The best thing to do would be right click on your class and choose Extract interface.

Upvotes: 42

Dave Black
Dave Black

Reputation: 8009

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

You should be passing the objects that are being mocked to the constructor, not the mocks themselves. TLDR; Use the Object property on the mocks.

Upvotes: 0

Suhas
Suhas

Reputation: 8448

Change the last line to

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

and it should work

Upvotes: 118

Related Questions