Monday 29 October 2012

Supported OS for .NET 4.5

Every time a new version of .NET framework is released, there is an associated cost :). Check out the list of supported client and server operating systems here. .NET 4.5 works on following OS:

1. Windows 8 (32 bit and 64 bit)
2. Windows 7 (32 bit and 64 bit)
3. Windows Vista SP2 (32 bit and 64 bit)
4. Windows Server 2012 (64 bit)
5. Windows Server 2008 R2 (64 bit)
6. Windows Server 2008 SP2 (64 bit)

So if you are planning to migrate your application to .NET 4.5, you might want to check the current state of hardware you possess. For example .NET 4.5 is not supported on Windows Server 2003.

Saturday 27 October 2012

Unit testing using Microsoft Fakes

Visual Studio 2012 has a very valuable feature called "Fakes" for the purpose of unit testing. Till now, our best bets were to use an Open Source or licensed third party solutions for mocking an object (interface or class) e.g. Moq, RhinoMock. Pex and Moles are also great solutions for mocking and test data generation using code analysis but they can not be used in commercial solutions. But with Visual Studio 2012, most of those features are built in.
Here is a simple example - Imagine a simple application which has a interface based implementation of business logic component and data access component : IBusinessComponent, IDataComponent are the interfaces and BusinessComponent and DataComponent implement the interfaces respectively. 


public interface IBusinessComponent
    {
        Customer GetCustomer(int customerId);

        Customer CreateCustomer(Customer customer);

        Customer UpdateCustomer(Customer customer);

        bool DeleteCustomer(int customerId);
    }


public interface IDataComponent
    {
        Customer GetCustomer(int customerId);

        Customer CreateCustomer(Customer customer);

        Customer UpdateCustomer(Customer customer);

        bool DeleteCustomer(int customerId);
    }

public class BusinessComponent : IBusinessComponent
    {
        private IDataComponent dataComponent;

        public BusinessComponent(IDataComponent dc)
        {
            this.dataComponent = dc;
        }

        public Customer GetCustomer(int customerId)
        {
            return this.dataComponent.GetCustomer(customerId);
        }

        public Customer CreateCustomer(Customer customer)
        {
            return this.dataComponent.CreateCustomer(customer);
        }

        public Customer UpdateCustomer(Customer customer)
        {
            return this.dataComponent.UpdateCustomer(customer);
        }

        public bool DeleteCustomer(int customerId)
        {
            return this.dataComponent.DeleteCustomer(customerId);
        }
    }


 public class DataComponent : IDataComponent
    {
...

public Customer GetCustomer(int customerId)
        {
            return customers.Where(c => c.Id == customerId).FirstOrDefault();
        }
...
}

We can simply add a unit test project to the solution and add reference of the 





project that has the core logic. Generating a "Fake" assembly is as straightforward as right clicking on the newly added reference and selecting "Add Fake Assembly" option. This adds fakes for the types present in the assembly. Now i can add mock of data component and write unit test that tests implementation in business component.

[TestMethod]
        public void GetCustomerTest()
        {
            FakesTesting.Interfaces.IDataComponent dataComponent = new FakesTesting.Interfaces.Fakes.StubIDataComponent()
                {
                    GetCustomerInt32 = (customerId) => { return new Customer() { Id = customerId }; }
                };
            FakesTesting.Interfaces.IBusinessComponent businessComponet = new FakesTesting.BusinessComponent(dataComponent);
            Customer c = businessComponet.GetCustomer(5);
            Assert.IsNotNull(c);
        }

        [TestMethod]
        public void GetCustomerTest2()
        {
            FakesTesting.Interfaces.IDataComponent dataComponent = new FakesTesting.Interfaces.Fakes.StubIDataComponent()
            {
                InstanceBehavior = new CustomStubBehaviorForDataComponent(),
                InstanceObserver = new CustomStubObserverForDataComponent(),
            };

            FakesTesting.Interfaces.IBusinessComponent businessComponet = new FakesTesting.BusinessComponent(dataComponent);
            Customer c = businessComponet.GetCustomer(5);
            Assert.IsNull(c);
        }
public class CustomStubBehaviorForDataComponent : IStubBehavior
{

 public TResult Result(TStub target, string name) where TStub : IStub
        {
            return default(TResult);
        }

        public bool TryGetValue(object name, out TValue value)
        {
            value = default(TValue);
            return true;
        }

        public void ValueAtEnterAndReturn(TStub target, string name, ref TValue value) where TStub : IStub
        {
            
        }

        public void ValueAtReturn(TStub target, string name, out TValue value) where TStub : IStub
        {
            value = default(TValue);
        }

        public void VoidResult(TStub target, string name) where TStub : IStub
        {
            
        }

}

public class CustomStubObserverForDataComponent : IStubObserver
    {
        public void Enter(Type stubbedType, Delegate stubCall, params object[] args)
        {
           
        }

        public void Enter(Type stubbedType, Delegate stubCall, object arg1, object arg2, object arg3)
        {
            
        }

        public void Enter(Type stubbedType, Delegate stubCall, object arg1, object arg2)
        {
            
        }

        public void Enter(Type stubbedType, Delegate stubCall, object arg1)
        {
            
        }

        public void Enter(Type stubbedType, Delegate stubCall)
        {

        }
    }



You can use any of the 2 approaches - 1. standard implementation redirection for method(s) 2. Finer mock behavior using custom implementations of IStubBehavior and IStubObserver interfaces.

Good thing about this framework is that you can generate stubs (mocking an interface's or class's implementation) and shims (mocking an implementation that you can not change e.g. System.DateTime) for assemblies that were compiled against older versions of .NET framework.