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
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Hi

I tried 2 methods of mocking out static calls on SPSecurity.RunWithElevatedPrivileges on Sharepoint 2010:

1. Isolate.WhenCalled(() => SPSecurity.RunWithElevatedPrivileges(() => { })).DoInstead((ctx) => Console.WriteLine("called"));

2. var mock = MockManager.Mock(typeof(SPSecurity), Constructor.Mocked);
mock.MockMethodCalled += new MockMethodCalledEventHandler(mock_MockMethodCalled);

both of them fail with error:

Test 'ConsoleApplication1.Tests.test1' failed: System.TypeInitializationException : The type initializer for 'Microsoft.SharePoint.SPSecurity' threw an exception.
----> TypeMock.TypeMockException :
*** Faking behavior on struct Microsoft.SharePoint.SPSecurity+SPOperationEntry is not supported in the following cases:
1. Faking behavior on more than one struct of the same type.
2. Faking behavior on more than one method on the same struct.
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)
Program.cs(27,0): at ConsoleApplication1.Tests.<test1>b__1()
at TypeMock.MockManager.a(String A_0, String A_1, Object A_2, Object A_3, Boolean A_4, Boolean A_5, Object[] A_6)
at TypeMock.InternalMockManager.getReturn(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Boolean isInterceptedType)
Program.cs(24,0): at ConsoleApplication1.Tests.test1()
--TypeMockException
at f9.a(Type A_0, Object A_1, MethodBase A_2, String A_3, TypeParams A_4)
at f9.a(Object A_0, String A_1, String A_2, MethodBase A_3, Object[] A_4, Object A_5)
at TypeMock.MockManager.a(String A_0, String A_1, Object A_2, Object A_3, Boolean A_4, Boolean A_5, Object[] A_6)
at TypeMock.InternalMockManager.getReturn(Object that, String typeName, String methodName, Object methodParameters, Boolean isInjected, Boolean isInterceptedType, Object p1, Object p2, Object p3, Object p4, Object p5)
at Microsoft.SharePoint.SPSecurity.SPOperationEntry..ctor(SPOperationCode code, SPOperationType type, Boolean bSiteAdmin, Boolean bSlowOprations, SPBasePermissions perm)
at Microsoft.SharePoint.SPSecurity..cctor()


My Question: Is it possible to fake this call? And how?
asked by damiand2 (2k points)

10 Answers

0 votes
Hi,

I run the example you posted and got the same results.
This a bug :evil:
We'll update you once it is fixed.
answered by ohad (35.5k points)
0 votes
Hi,

I found a workaround for the problem:
Simply fake the static constructor of SPSecurity class before you fake any methods on it.
So the test should be:
Isolate.Fake.StaticConstructor(typeof(SPSecurity));
Isolate.WhenCalled(() => SPSecurity.RunWithElevatedPrivileges(() => { })).DoInstead((ctx) => Console.WriteLine("called"));


Please let me know if works for you.
answered by ohad (35.5k points)
0 votes
Now problem occurs with code below:

Isolate.Fake.StaticConstructor(typeof(SPSecurity));
Isolate.WhenCalled(() => SPSecurity.RunWithElevatedPrivileges(() => { })).DoInstead((ctx) => ((SPSecurity.CodeToRunElevated)ctx.Parameters[0])());
var fakeSite = Isolate.Fake.Instance<SPSite>(Members.ReturnRecursiveFakes);
Isolate.Swap.AllInstances<SPSite>().With(fakeSite);

SPSecurity.RunWithElevatedPrivileges(() => Console.WriteLine("nice"));
SPSite site = new SPSite("http://fake.com/fake"); //still nice
SPSecurity.RunWithElevatedPrivileges(() => site = new SPSite("http://fake.com/fake")); //not nice, original SP call


Apparently now when we execute code inside mocked out RunWithElevatedPrivilieges no mocks are present and original calls to SP take place.
answered by damiand2 (2k points)
0 votes
Hi,

The behavior you see is due to a known limitation of DoInstead:
Fakes can not work inside DoInstead since the callback is invoked inside the Isolator and fakes can not be created inside the Isolator.

Can you please try to explain what are you trying to do in the test?
We'll try to help you out with it.
answered by ohad (35.5k points)
0 votes
Sure.

Everywhere in my production code i have following statements:

SPSecurity.RunWithElevatedPrivileges(
()=> new SPSite(...).OpenWeb()... //etc.
);

Could you please provide me with info how to use TypeMock to write unit tests for such code (so it can be run on build server without sharepoint installed)?

I need to mock out call to RunWithElevatedPrivileges and i need mocks for Sharepint objects inside.
answered by damiand2 (2k points)
0 votes
Any news on how to make this work?
answered by damiand2 (2k points)
0 votes
Damian,

Sorry about taking this long to get back to you. We've been trying to work around the mentioned limitation, and finally managed to implement a fix that will allow fakes in DoInstead() in most scenarios. I will send it to you offline through our support email.

Doron Peretz
Typemock Support
answered by doron (16.5k points)
0 votes
You mentioned that there is a solution to the problem can you please post it?

As everything works until the code under test tries to create the SPSite then I get the following error:

System.InvalidOperationException was unhandled by user code

Message=This operation can be performed only on a computer that is joined to a server farm by users who have permissions in SQL Server to read from the configuration database. To connect this server to the server farm, use the SharePoint Products and Technologies Configuration Wizard, located on the Start menu in Administrative Tools.


I assume that inside the delegate TypeMock cannot create the fakes?

Is there a way to do this properly?
answered by jonnob (140 points)
0 votes
Hi,

What version are you using?
The latest version of the Isolator (6.0.6) has this ability.

Please try it and let me know if solves the problem.
answered by ohad (35.5k points)
0 votes
Try the following code. It has been tested and it seems to be working fine.

Paste this function in your Test Fixture:

public static void SecuritycMockMockMethodCalled(object sender, MockMethodCallEventArgs e)
        {
            if (e.CalledMethodName.Equals("RunWithElevatedPrivileges"))
            {
                var del = (SPSecurity.CodeToRunElevated)e.SentArguments[0];
                var res = del.BeginInvoke(null, null);
                res.AsyncWaitHandle.WaitOne();
                del.EndInvoke(res);
            }
        }


And then paste these lines in your tests:

var securityMock = MockManager.Mock(typeof(SPSecurity));
            securityMock.MockMethodCalled += new MockMethodCalledEventHandler(SecuritycMockMockMethodCalled);
            securityMock.ExpectAlways("RunWithElevatedPrivileges");


Let me know if you need further help.

Regards,
Agustín Burgos.
answered by agustinlburgos (140 points)
...