Question

I am pulling my hair out with this one. I have looked and cannot find a simple, clear example of creating and using a partial stub with Microsoft Moles. Maybe I'm missing somethimg, or have my code architected poorly, but I can't seem to get this to work.

Here's my class (simplified):

public class AccountService : IAccountService {
        private readonly webServiceProxy IExternalWebServiceProxy;

    public AccountService(IExternalWebServiceProxy webServiceProxy) {
        this.webServiceProxy = webServiceProxy;
    }

    public List<AccountModel> GetAccounts(string customerId) {
         var returnList = new List<AccountModel>();
         var xmlResponse = webServiceProxy.GetAllCustomerAccounts(customerId);

         var accountNodes = xmlResponse.SelectNodes("//AccountNodes");
            if (accountNodes != null)
            {
                foreach (XmlNode node in accountNodes)
                {
                    var account = this.MapAccountFromXml(node);

                    if (!string.IsNullOrEmpty(account.AccountNumber))
                    {
                        returnList.Add(account);
                    }
                }
            }

            return returnList;
    }

    public AccountModel MapAccountFromXml(XmlNode node) {
        if (!IsValidAccount(node) {
            return null;
        }

        // This performs a lot of XML manipulation getting nodes based on attributes 
        // and mapping them to the various properties of the AccountModel. It's messy 
        // and I didn't want it inline with the other code.

        return populatedAccountModel;
    {

    public bool IsValidAccount(XmlNode node) 
    {
        var taxSelectValue = node.SelectSingleNode("//FORMAT/Field[@taxSelect='1']").First().Value;
        var accountStatus = // similar to first line in that it gets a single node using a specific XPath
        var maturityDate = // similar to first line in that it gets a single node using a specific XPath
        var maturityValue = // similar to first line in that it gets a single node using a specific XPath

        return taxSelectValue != string.Empty && taxSelectValue != "0" && (accountStatusValue != "CL" || (maturityDate.Year >= DateTime.Now.AddYears(-1).Year));
    }
}

What I want to do is test my GetAccounts() method. I can stub out the IExternalWebServiceProxy call and return fake XML, but I have internal calls happening in my service since my GetAccounts() method calls MapAccountFromXml() which in turn calls IsValidAccount().

Perhaps the solution is to not worry about breaking out the long and involved MapAccountFromXml() and IsValidAccount() code and just put them inline into the GetAccount() call, but I would rather leave them broken out for code readability.

I have my Moles assembly created, and know I can create a stub version of my class like this

var stubWebService = SIExternalWebServiceProxy {
       GetAllCustomerAccounts = delegate {
            return SomeHelper.GetFakeXmlDocument();
       }
}

var stubAccountService = new SAccountService() { callsBase = true; }

My problem is I don't know how to then override the internal calls to MapAccountFromXml and IsValidAccount and I don't want my Unit Test to be testing thos methods, I'd like to isolate GetAccounts for the test. I read somewhere the methods need to be virtual to be overriden in a partial stub, but could not find anything that then showed how to create a stub that overrides a few methods while calling the base for the one I want to test.

Was it helpful?

Solution

Peer put me on the right track, thank you.

It turned out that what I was looking for is called Detours in Moles. Rather than stub an interface using

var stubAccountService = new SIAccountService();

what I needed to do was create an instance of my AccountService and then detour all calls to the methods I wanted to mock, like this

var accountService = new AccountService();

MAccountService.AllInstances.MapAccountFromXmlXmlNode = delegate { 
    return new AccountModel(); 
};

The MAccountService is provided by Moles when you Mole your assembly. The only missing piece to this is that for this to work you need to add the following attribute to your test method:

[HostType("Moles")]

This worked for me locally, but in the end I had trouble getting TFS to do automated builds

UPDATE

I just stumbled on another way of doing this, while looking at Rhino Mocks. If the methods in the class being mocked are virtual then you can override them in the mock, like this:

var accountService = new SAccountService();
accountService.MapAccountFromXmlXmlNode = delegate
    {
        return new AccountModel();
    }

Now I can call

accountService.GetMemberAccounts();

and when accountService makes its call to MapAccountFromXml it will be caught by the stub and processed as I deem necessary. No messing with HostType and it works like a charm.

OTHER TIPS

To test methods in you class in issolation you do this with moles by making a mole for the IsValidAccount and MapAccountFromXml methods. Or make a stub implementation with stubs where you let the stub call the orriginal methode using base. Or what I think is a nicer solution, make a test class which overrides the methods you do want to stub (this is the same what a stub would do, except you see all what is happening in your own code):

public class TestHelperAccountService : AccountService {

    public override AccountModel MapAccountFromXml(XmlNode node) {
        return new AccountModel(){
                    //Accountmodelstub
              };
    {

    public override bool IsValidAccount(XmlNode node) 
    {
        return true;
    }
}

This way you can do your test for the GetAccount method on your TestHelperAccountService class where you GetAccount method runs in full issolation. You can do the same for the methods like MapAccountFromXml to test them seperatly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top