chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
How I mock COM objects? My test code will always call the actual Load method not the mock one.

Service Class
public IProduct GetProduct()
{
ILoader iLoader = new LoaderClass();
IProduct iProduct = (IProduct)iLoader.Load();
return iProduct;
}


Test code

Mock mock1 = MockManager.Mock<LoaderClass>();
MockObject mock2 = MockManager.MockObject<ILoader>();
MockObject mock3 = MockManager.MockObject<IProduct>();
mock2.ExpectAndReturn("Load", (IProduct)mock3.Object);

Service service = new Service();
IProduct iProduct = service.GetProduct();
Assert.IsNotNull(iProduct);
asked by JK (3.1k points)

6 Answers

0 votes
The problem with COM proxy objects is that part of them is in MSCorLib which Isolator doesn't Mock at this time.

Every COM object has an interface - so instead you can create a mock for that interface - for example:

Mock mock1 = MockManager.Mock<ILoader>(); 
answered by dhelper (11.9k points)
0 votes
Then I get TypeMockException "Cannot type mock Interfaces or Abstract classes use MockObject"
answered by JK (3.1k points)
0 votes
The error message is right -

Mock is used to return an actual mocked instance while MockObject is intended to be used with future instances.
And so you need to declare a MockObject instead so that the next instance created from ILoader shall be Mocked

I would like to have a look at the COM class you've been trying to Mock - let's take it offline.
answered by dhelper (11.9k points)
0 votes
I would like to clear things up as this is a delicate distinction.

Dror's explanation is right but actually it's the other way around:
- Mock is used to set behavior and expectations of objects that have not yet been created. A Mock will become active once an object of the type being mocked is instantiated.
- MockObject on the other hand creates an object to work with and is used to set behavior and expectations of that specific instance.

An after effect of this distinction is that interfaces and abstract classes cannot be used in conjunction with Mock - instances cannot be created for these constructs so a Mock of that type would never become active. The aforementioned error message tells you right that - cannot use Mock with an interface or abstract class, use MockObject instead. MockObject instantiates an instance of the class (Typemock Isolator can do that even for interfaces and abstract classes) which eliminates the problem.

Confusing? we think so too... This confusion is cleared up with the AAA syntax, and you don't need to mess around with Mocks/MockObjects. Instead, you work with a fake instance of the class being faked, and you can define it will be used on a future instantiation. Also, you can use the Recursive Fakes feature that allows you to fake an entire object model instead of messing with setting each call's return value:

// create a recursive fake of ILoader - calls to ILoader methods will return fake values
ILoader fakeLoader = Isolate.Fake.Instance<ILoader>(Members.ReturnRecursiveFakes);

// Swap the next instantiation of LoaderClass with the fake loader
Isolate.Swap.NextInstance<LoaderClass>().With(fakeLoader);

// Thats all the set up you need (2 lines instead of 4...
// Now we run the test and assert the results
Service service = new Service();
Assert.IsNotNull(service.GetProduct());


Please let us know if this works for you, or if you need any help using AAA.

Doron
Typemock support
answered by doron (17.2k points)
0 votes
Looking at my test code again, it seems to me that the object being swapped in for the future instance of LoaderClass should be assignable to LoaderClass - this means that you will need fakeLoader to be a fake object of LoaderClass rather than ILoader:

var fakeLoader = Isolate.Fake.Instance<LoaderClass>(Members.ReturnRecursiveFakes);


Doron
answered by doron (17.2k points)
0 votes
Thanks for the examples but I was not able to mock my LoaderClass. I managed to mock my interfaces so I created a wrapper for my LoaderClass. It's not the ideal way but now I can at least run my tests.
answered by JK (3.1k points)
...