tags:

views:

48

answers:

1

I have a class that does some retrieving of contents, and it has a method that requires some inputs (filters) before retrieving it. One of the "input" calls another method, which basically returning an int, how do I mock it using MOQ? Here's an example:

namespace MyNamespace
{
    public class ConfigMetaDataColumns : MyModel
    {
        public int FieldID { get { return ValueInt("FieldID"); } }
        public int OrderId { get { return ValueInt("OrderId"); } }
        public string Label { get { return ValueString("Label"); } }
        public string FieldName { get { return ValueString("FieldName"); } }
        public int IsReadOnly { get { return ValueInt("IsReadOnly"); } }
    }

    public class GetDataClass
    {
        protected OpenSQLAccessLayer m_WITObject;

        // Input Properties
        public string GroupID;
        public string PageName;

        // Output Properties

        /// <summary>
        /// Get Config meta data
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ConfigMetaDataColumns> GetConfigMetaData()
        {
            var requester = new ListRequester<OpenSQL, ConfigMetaDataColumns>(m_WITObject, "Result[0].RowCount", "Result[0].Row[{0}].");

            return requester.Items;
        }

        public void InitRequest()
        {
            User user = (User)HttpContext.Current.User;
            m_WITObject = user.NewService<OpenSQLAccessLayer>();

            m_WITObject.SetInput("MultipleResultSets", 1);
            m_WITObject.SetInput("ClientID", Utils.GetClientID());
            m_WITObject.SetInput("GroupID", GroupID);
            m_WITObject.SetInput("PageName", PageName);
            m_WITObject.Retrieve();
        }
    }
}

This is the "GetClientID()" method:

public static int GetClientID()
        {
            User oUser = (User)HttpContext.Current.User;
            int nClientID;
            string sClientID = string.Empty;

            if (String.IsNullOrEmpty(oUser.Session("clientid")))
            {
                Client oClient = new Client();
            }

            oUser = (User)HttpContext.Current.User;
            sClientID = oUser.Session("clientid");




            //If we couldn't retrieve it, throw exception
            if ( string.IsNullOrEmpty(sClientID) || !int.TryParse(sClientID, out nClientID))
            {
                throw new Exception("No clientid found in user session, client not authenticated, please login from main page");
            }

            return nClientID;
        }

I'm just looking for a way for me to pass in a hard-coded value for the ClientID, and use this to do some unit testing with the GetDataClass class.

Thanks.

+3  A: 

You cannot mock a static method. You should use some means of dependency injection. Say you make your GetClientId method part of an interface called IUtils like so:

public interface IUtils
{
    int GetClientId();
} 

And you have your concrete class Utils implemented as above, but without the method being static (and implementing the interface of course). You now inject an implementation of your interface into the GetDataClass class by changing its constructor, like so:

public class GetDataClass
{
     private readonly IUtils utils;

     public GetDataClass(IUtils utils)
     {
         this.utils = utils;
     }

     //SNIP
}

In the InitRequest method you change the call Utils.GetClientID() to this.utils.GetClientId().

You are now ready to instantiate your GetDataClass class with a mock, like so:

var utilsMock = new Mock<IUtils>();
utilsMock.Setup(u => u.GetClientId()).Returns(42);

var getDataClass = new GetDataClass(utilsMock.Object);
getDataClass.InitRequest();

And that's it.

klausbyskov
Hi klausbyskov, unfortunately, the "Utils" class (as well as a load of others classes are already implemented by a different team!), none are implementation of interfaces so I can't make any changes to it. Perhaps, I should rephrase my question: Based on the information in my original question, how can I test **"GetDataClass"** (it needs to call the "**InitRequest"** to do some initializes), and specifically, calling **"GetConfigMetaData()"** ? Thanks.
Saxman
What prevents you from refactoring the *other teams* ' code? After all, you are all in the same boat. If you explain your intentions of making the code testable, I'm sure they will *have to* try to accommodate your wishes if they don't want to look like complete fools professionally. It will do you *all* good in the long run to use industry best practices in your development, and that definitely includes writing testable code. So instead of looking for a solution (that does not exist) to a design problem that should not be there, just refactor the code. It should not be that big of a deal.
klausbyskov
This class (among many other classes) is part of a "Core" library that has been written by a different team that is being used by about 15 different projects. I'm pretty new here so my voice is wayyyyyy down the pipeline :) but fair enough, I'll press to have this library refactor for testable codes. Thanks!
Saxman
@Saxman, I can see how that might be a problem for you, but it is the only way that you can inject a Moq mock. Static methods simply cannot be mocked. Good luck with it.
klausbyskov