Unit test private methods?

There has been a lot of discussion about whether we should unit test private methods, which I find it very interesting to read on my spare time). However, in this post I am not going to add more arguments on this subject (I will leave it to your own discretion 🙂 ). Here, I am going to show an example on using PrivateObject class which can be handy if you need to test a private method or property or field. The class exists in Microsoft Visual Studio Unit Test and you can read on MSDN for more information. In short, this class gives access to private methods (and properties). Let’s say I have an Account class which I want to test:

public class Account
    {
        public decimal InterestRate { get; private set; }        
        private decimal _balance;
        private int _accountId;

        public Account(int accountId)
        {
            _accountId = accountId;
        }

        private void InitAccount()
        {
            //Populate Account details, i.e. current balance
        }

        public decimal GetBalanceWithInterest()
        {
            return _balance + GetInterest();
        }

        private decimal GetInterest()
        {
            return _balance*InterestRate;
        }
    }

If I want to test the GetInterest method, which is private, I could do the following:


 [TestMethod]
        public void GetInterest_ReturnsExpectedInterest()
        {
            decimal balance = 1000;
            decimal interestRate = (decimal) 0.05;
            decimal expectedInterest = 50;

            var acc = new Account(1000);
            var privateObject = new PrivateObject(acc);

            privateObject.SetField("_balance", balance);
            privateObject.SetProperty("InterestRate", interestRate);

            var interest = privateObject.Invoke("GetInterest");

            Assert.AreEqual(interest, expectedInterest);
        }

The example above invokes the private method without passing any arguments. To pass arguments, you can use an array of object as follows:


privateObject.Invoke("APrivateMethod", new object[] { param1, param2});

That’s it, quite simple isn’t 🙂

Advertisements

Building custom OData service on SharePoint 2010

Recently I had a task to build a custom OData service for SharePoint, so here are the steps:

First, need to make sure that ADO.Net data service framework is installed on SharePoint server:
ADO.Net for Windows 2008
Or
ADO.Net for Windows 2008 R2

After that, add the following references on the project:

  • System.ServiceModel
  • System.ServiceModel.Web
  • System.ServiceModel
  • System.Runtime.Serialization
  • System.Data.Services
  • System.Data.Services.Client
  • Microsoft.SharePoint.Client.ServerRuntime

The next step is to create a SharePoint Mapped Folder and then select ISAPI. This is the folder where we are going to create our .svc file. Open the svc file and make sure it uses MultipleBaseAddressDataServiceHostFactory.

<%@ ServiceHost Language="C#" Debug="true" Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressDataServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
    Service="TestODataService.EmployeeService,$SharePoint.Project.AssemblyFullName$" %>

In my project, I have created the following classes

[Serializable]
    [DataContractAttribute(IsReference = true)]
    [DataServiceKey("EmployeeId")]
    public class Employee
    {
        [DataMemberAttribute]
        public int EmployeeId { get; set; }

        [DataMemberAttribute]
        public string FirstName { get; set; }

        [DataMemberAttribute]
        public string LastName { get; set; }
    }
public class DataContext
    {
        public IQueryable<Employee> Employees
        {
            get
            {
                List<Employee> employeeList = EmployeeStore.GetEmployees();

                return employeeList.AsQueryable();
            }
        }

        
    }

In this case the DataContext class will be used as the data source type.

The last one is the EmployeeService itself, which inherits from DataService class

[BasicHttpBindingServiceMetadataExchangeEndpoint]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    [System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class EmployeeService : DataService<DataContext>
    {
        [WebGet]
        public IQueryable<Employee> GetEmployeeByName(string name)
        {
            var searchResult = EmployeeStore.GetEmployees()
                                        .Where(e => e.FirstName.Contains(name) || e.LastName.Contains(name));

            return searchResult.AsQueryable();
        }

        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    }

Please note that I have set access to all entities and service operations to AllRead since I only need to read the data.

To consume the above service, we can add a service reference in our test project and use the url to the service, e.g.: http://localhost/_vti_bin/EmployeeService.svc

To get access to the entities, we can use the data context as below:

var ctx =
              new ServiceReference1.DataContext(new Uri("http://localhost/_vti_bin/employeeService.svc"));
            ctx.Credentials = System.Net.CredentialCache.DefaultCredentials;

            ctx.Employees.ToList().ForEach(e => Console.WriteLine(e.FirstName + " " + e.LastName));

To use the service operations:

var ctx =
              new ServiceReference1.DataContext(new Uri("http://localhost/_vti_bin/employeeService.svc"));
            ctx.Credentials = System.Net.CredentialCache.DefaultCredentials;
var query = ctx.CreateQuery<Employee>("GetEmployeeByName").AddQueryOption("name", "'Blogg'");
            var result = query.Execute();

            result.ToList().ForEach(e => Console.WriteLine(e.FirstName + " " + e.LastName));

Using SharePoint PeopleEditor user control

I had the chance to play with PeopleEditor user control on my previous project and just thought would be good to put another blog about it out there, so here you go:

Started with creating a visual web part and the next step is adding the control to the ascx page

<SharePoint:PeopleEditor ID="peUser" ValidatorEnabled="true" runat="server"
                        SelectionSet="User" Width="350px" IsValid="true" AllowTypeIn="true"
                        MultiSelect="true"></SharePoint:PeopleEditor>
<SharePoint:InputFormRequiredFieldValidator ID="rfvUser" 
                        SetFocusOnError="true" runat="server" ControlToValidate="peUser" BreakBefore="true"
                        ErrorMessage="Required field." EnableClientScript="false"
                        Display="Dynamic"></SharePoint:InputFormRequiredFieldValidator>

To get the selected users we can iterate through its resovedEntities property

for (index = 0; index <= peControl.ResolvedEntities.Count - 1; ++index)
{
    PickerEntity entity = (PickerEntity)peopleEdControl.ResolvedEntities[index];
    SelectedUser selectedUser = new SelectedUser(){ Id = Convert.ToInt32(entity.EntityData["SPUserID"])
                                                    , Name = entity.DisplayText
                                                    , LoginName = entity.Key };
    selectedUserList.Add(selectedUser);
}

To assign a value to PeopleEditor user control (in my case I use a string of login name separated by a semicolon)

string[] delimiter = { ";" };
string[] loginNames = loginNameString.Split(delimiter, StringSplitOptions.RemoveEmptyEntries);

foreach(string loginName in loginNames)
{
     PickerEntity pe = new PickerEntity();
     pe.Key = loginName;

     pe = peUser.ValidateEntity(pe);
     ArrayList entityList = new ArrayList() { pe };

     peUser.UpdateEntities(entityList);
}

Hope that helps 🙂

Working with Oracle Object Types part 2

Following previous post about working with Types in Oracle, this post will focus on using the types from .Net.

The easiest way to map the Oracle Types is by using Oracle .Net Data Provider (ODP) to generate the class for you:
– Open Server Explorer (Tools – Server Explorer)
– Add new connection (right click Data Connections and choose add connection), set Data source to Oracle Database and Data provider to Oracle Data Provider for .Net
– Fill up some connection details and press Ok
– At this stage you should be able to see the mapping of every Oracle object in Server Explorer (well, maybe not everything)
– Go to User-Defined Types node and choose one of the Types
– Right click on the type, Generate Custom Class, follow the wizard and click Finish

From previous post, I got USER_TYPE and USER_TAB objects generated and to use those objects from .Net:

OracleConnection conn = NEW OracleConnection(connectionString);

IF (conn.State == ConnectionState.Closed)
{
conn.Open();
}

try
{
    OracleCommand oCmd = NEW OracleCommand();
    oCmd.CommandText = "USERPKG.GetUsers";
    oCmd.Connection = conn;
    oCmd.CommandType = CommandType.StoredProcedure;
    oCmd.BindByName = true;

    OracleParameter nameParam = oCmd.PARAMETERS.ADD("userId", OracleDbType.Int32);
    nameParam.Value = userId;
    nameParam.Direction = ParameterDirection.Input;

    OracleParameter listParam = NEW OracleParameter("USER_TAB", OracleDbType.OBJECT);
    listParam.Direction = ParameterDirection.ReturnValue;
    listParam.UdtTypeName = "USER_TAB";
    oCmd.PARAMETERS.INSERT(0, listParam);

    oCmd.ExecuteNonQuery();
    USER_TAB searchResult = (USER_TAB)oCmd.PARAMETERS["USER_TAB"].Value;
    RETURN searchResult;
}
finally
{
    IF (conn.State == ConnectionState.Open)
    {
        conn.Close();
    }
}

As we are using oracle type, the UdtTypeName needs to be declared. So far this is the easiest way that I can find to use Oracle data types from .Net 🙂

Convert a string or an integer to enum type

Something that I always use whenever I use enumeration :

public enum StatusType
	{
		Approved = 1,
		Pending = 2,
		Cancelled = 3
	}

Convert a string to enum :

string currentStatus = "Approved";
StatusType status = (StatusType) Enum.Parse(typeof(StatusType), currentStatus);

Convert an int to enum :

int currentStatusId = 1;
StatusType type = (StatusType) Enum.ToObject(typeof(StatusType), currentStatusId); 

Just be careful with enum conversion, especially when you want to use Enum.IsDefined method as it is very expensive.