Tuesday, July 29, 2008

TDDing a CRM 4.0 Plugin - Part 3

In Part 2 I showed you how to TDD the reading of the PostImage entity images from the plugin context. This part will go over how to mock the call to the webservice.

To review, at this point we have gotten the DynamicEntity object out of the plugin context. Now we need to do something useful with it. We will hand it off to a custom built webservice (this is not the CRM webservice) for external processing. There are many different ways to handle an integration like this. I'd prefer something a bit more fail-safe like having a Biztalk server receive the message and process it. In our case though, it couldn't matter less.

So let's start with our test case to make sure our webservice method is called. The first question I always have when starting a new test case is whether to create a new one, or expand on an old one. In this case, we're adding to the basic "happy path" of the plugin. We could create a new test case but it would largely contain all the same code as before. Moreover, as soon as I added in the additional code, I'd have to add the test code (like the Expect calls) to the first test case. In the end, I'd end up with two identical test cases. I don't want to get into the debates here as they're off-track from the discussion at hand. For simplicity, I'm going to add to the old test case.

I need to add a new "Expect" call to the test case to make sure the webservice is getting called. Since the intent of the test is changing, let's rename the method to:


public void Execute_HappyPathExecutesAsExpected()


I've already mocked the object out (IWebServiceWrapper webService) so no need to add additional code there. So all there is to do is add the new expect clause:


[Test]
public void Execute_HappyPathExecutesAsExpected()
{
DemoPlugin plugin = GetDependencyInjectedPlugin();

DynamicEntity account = CreateSampleAccountDEWithPopulatedValues();
PropertyBag postEntityImages = CreatePropertyBagWithAccount(account);
SetupExpectationsThatPostEntityImagePropertyBagIsRead(postEntityImages);

// new code
Expect.Once.On(webService).Method("UpdateAccount").With(account);
// end new code

plugin.Execute(context);
mock.VerifyAllExpectationsHaveBeenMet();

}


If I run the test, I can see it fails because our method called "UpdateAccount" doesn't exist yet. We should resolve this error first because the test case fails in validating the test case code, not because the production code isn't written yet. So, add the UpdateAccount method to the IWebServiceWrapper interface and the implementing class (so the project compiles):


public class MyWebService : IWebServiceWrapper
{
public void UpdateAccount(DynamicEntity account)
{

}
}

public interface IWebServiceWrapper
{
void UpdateAccount(DynamicEntity account);
}


Good, now when we run the test we see that not all of our expectations were met. Perfect! Now that we know our test is valid, we can write the code that makes the test pass:


public void Execute(IPluginExecutionContext context)
{
DynamicEntity account = (DynamicEntity) context.PostEntityImages["postImage"];
webService.UpdateAccount(account);
}


And when we run out test we can see it now passes!

We'll skip the refactoring this time around as there isn't much to do other then just throwing the new Expect call into it's own method.

Stay tuned for Part 4, where I'll show you how to simulate calls to the CRM WebService.

=-}

No comments: