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
Hi,

I have a simple question: Is it possible (and if how) to mock static classes and their static methods?
The problem: The tested class calls System.Windows.Forms.Clipboard.GetDataObject (and in another method SetDataObject). As I don't want to manipulate the clipboard while testing I want to mock these two methods.
The first problem I encountered: I don't get the type for "Clipboard" in normal matter (that is Type.GetType("System.Windows.Forms.Clipboard")).
The other question is if TypeMock is able to mock an already instantiated (static) class.

Thanks for any helpful answer,

Michael
asked by mknaup (8.5k points)

4 Answers

0 votes
Hi Michael
Is it possible (and if how) to mock static classes and their static methods?

:( If you are talking about .NET 2.0 static classes then TypeMock 2.3 doesn't support .NET 2.0, (A Beta program for .NET 2.0 will be starting soon)
:arrow: Mocking static methods is simple and is one of TypeMocks beauties, just mock the class and the method, see the "first mock" topic in the documentation and the examples included in the installation folder (if you installed them).
:idea: There is no difference if you use Mock or MockAll for static members as static members have no instance.

I don't get the type for "Clipboard" in normal matter (that is Type.GetType("System.Windows.Forms.Clipboard")).

:?: How do you get the type? Why not use typeof(Clipboard)?
is TypeMock able to mock an already instantiated (static) class.

:arrow: I don't quite follow, what is an instantiation of a static class?
Anyhow, TypeMock can mock already instantiated classes simply by using MockAll
(Note: Types that are instantiated BEFORE MockManager.Init() is called for the first time cannot be mocked, See "Fast Mode" in documentation for more details.)

Here is an example of your mock- all other methods run as normal (Constructor.NotMocked)
Mock clipboardMock = MockManager.MockAll(typeof(Clipboard),Constructor.NotMocked);
clipboardMock.ExpectAndReturn("GetDataObject",myIDataObject);
clipboardMock.ExpectCall("SetDataObject");


:idea: If you are using the enterprise edition you can also swap the parameters of the mocked methods
clipboardMock.ExpectUnmockedCall("SetDataObject").When(new Assign("test text").AndCheck("real text"));

The above code will call SetDataObject but will pass "test text" when "real text" is passed!!!

Of course if your tested code just uses GetDataObject, you can Clipboard.SetDataObject("test text") before calling you code, and you won't need to mock any classes
answered by scott (32k points)
0 votes
Hi Scott,

first of all thanks for the very detailed and helpful answer. Excuse me for my bad verbalism about "instantiated static classes".

Your code works quite fine. Now I want to check the argument that SetDataObject receives. I tried
this.clipboardMock.MethodSettings("SetDataObject").MockMethodCalled +=
new MockMethodCalledEventHandler(clipboardMock_SetDataObjectCalled);

but the method clipboardMock_SetDataObjectCalled is not called. What am I doing wrong? The doc says: When static methods are called events from ALL mocks of that type are triggered.

Any idea?
Thanks in advance for help.

Michael
answered by mknaup (8.5k points)
0 votes
Hi Michael
If you want to check the arguments passed simply use the Args as follows:
clipboardMock.ExpectCall("SetDataObject").Args(expectedArg);

or
clipboardMock.ExpectCall("SetDataObject").Args(Check.BeginsWith("begin"));


but the method clipboardMock_SetDataObjectCalled is not called. What am I doing wrong? The doc says: When static methods are called events from ALL mocks of that type are triggered.

You have actually found a bug, :twisted: if you will use MockManager.Mock instead of MockAll it will work.
We will fix the bug
answered by scott (32k points)
0 votes
Hi Scott,

you wrote
Hi Michael
If you want to check the arguments passed simply use the Args as follows:
clipboardMock.ExpectCall("SetDataObject").Args(expectedArg);

or
clipboardMock.ExpectCall("SetDataObject").Args(Check.BeginsWith("begin"));


Thanks for your answer. Cause I need more flexibility I will use this:
this.clipboardMock.ExpectCall("SetDataObject").Args(Check.CustomChecker(
                        new ParameterCheckerEx(CheckParameter), Document));


Michael
answered by mknaup (8.5k points)
...