Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I've been tasked with writing a small C# tool to fetch and fiddle with some Sharepoint 2010 items using the Sharepoint Client Object Model (COM). The code will typically have something like this in the beginning:

public void foo(ClientContext clientContext ) {
    Web web = clientContext.Web;
    clientContext.Load(web);
    clientContext.ExecuteQuery();
    ...
}

To unit test this, I was planning to use Microsoft's Mole. So I try to make a test with a mock ClientContext like the following. The problem here is that I'm unable to make a mock implementation of the Load method.

MClientContext ctx = new MClientContext {
    WebGet       = () => new MWeb {},
    ExecuteQuery = () => {}
    //,Load = () => {} .... problem
};

VS tells me there's no definition for Load in Microsoft.SharePoint.Client.Moles.MClientContext.

The ClientContext's Load method is inherited from ClientRuntimeContext (I checked this with JustDecompile).

public void Load<T>(T clientObject, params Expression<Func<T, object>>[] retrievals)
where T : ClientObject
{
    if (clientObject == null)
    {
        throw new ArgumentNullException("clientObject");
    }
    DataRetrieval.Load<T>(clientObject, retrievals);
}

So the question is, how does one create a mock ClientContext with Mole, complete with the inherited Load method, for unit testing? Is there some other trick to unit testing Client Object Model code?

Anything from example snippets to links would be greatly appreciated.

note: I'm very new to Sharepoint (and C#.... and, tbh, mocking). note2: I'm not able to get the paid TypeMock version, which I'm told could possibly accomplish this.

## Update: Solved! Essential clues provided by Nathan below ##

MClientContext ctx = new MClientContext {
    WebGet       = () => new MWeb {},
    ExecuteQuery = () => {}
    /* .... */
};

var ctxBase = new MClientRuntimeContext(ctx);
ctxBase.LoadTExpressionOfFuncOfTObjectArray<ListItemCollection>((a,b) => {}); 

This means my Moled ClientContext can now do:

ctx.Load(someInstanceOfListItemCollection);
ctx.ExecuteQuery();
share|improve this question
    
Also, be aware that Microsoft is no longer actively developing Moles, from research.microsoft.com/en-us/projects/moles "The Fakes Framework in Visual Studio 2012 is the next generation of Moles & Stubs. Fakes is different from Moles, however, so moving from Moles to Fakes will require some modifications to your code. The Moles framework will not be supported in Visual Studio 2012." –  Nathan Aug 1 '13 at 15:26
add comment

1 Answer 1

up vote 2 down vote accepted
+50

The reason Visual Studio is telling you that "Load does not exist", is because you are not matching the method signature.

Your sample code shows that you are using Load = () => {} to attempt to define the behavior, however, the only signature (I'm looking at the SharePoint 2013 client object model here - "Microsoft.SharePoint.Client.dll, v15.0.0.0") for Load is

public void Load<T>(T clientObject, params Expression<Func<T, object>>[] retrievals)
                   where T : ClientObject;

You have told the compiler to look for a no-argument version of Load which doesn't exist.

So instead, you need to match the method signature. Having never used Moles myself, I can't guarantee this is correct, but I suspect you simply need to do something like:

MClientContext ctx = new MClientContext {
    WebGet       = () => new MWeb {},
    ExecuteQuery = () => {},
    Load = (clientObject, retrievals) => {}
};

I also note that it appears you are using "Moles" rather than "Stubs". Another approach would be to wrap all your calls to the ClientContext behind your own interface, which you could then provide stubbed implementations to for your test, and "real" implementations for your production code. To go that route, you will probably want to look at some sort of Dependency Injection framework.

Update

It also appears that to access a method from a base type in a Mole, you must Mole both the base type and the child type. See the Moles Manual page 20, in the section "Base Types", where it states:

The mole properties of base members can be accessed by creating a mole for the base type and passing the child instance as a parameter to the constructor of the base mole class.

share|improve this answer
    
Thanks, Nathan. The line that I commented out is indeed missing the args and therefore invalid, but Mole's MClientContext doesn't actually contain a Load member at all. I don't know if perhaps Moles somehow struggles with generic methods. As you say in the comment, VS 2012's Fakes has superseeded it, so I should presumably switch to that and try again. For now, I'm using a thin, stubbable wrapper class like your suggestion. –  Frode Aug 1 '13 at 15:37
    
Hi, I edited the answer with additional information on base types. However, in my own projects, I am personally wrapping the ClientContext access behind my own interface and using the Moq (code.google.com/p/moq) framework. –  Nathan Aug 1 '13 at 15:57
    
Thank you, Nathan. It seems I've shamelessly skipped that part of the manual. I've added the solution to the end of my question for future googlers, feel free to add it to your answer too. Thanks again! –  Frode Aug 2 '13 at 16:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.