Monday, March 28, 2016

How could we mock a non-virtual method from an external dependency.

Please choose 'View Source' in your browser to view the HTML, or File | Save to save this file to your hard drive for editing.

Introduction

Through this article, we are knowing about how we able to mock a non-virtual method with no interface implementation of an external object. To understand this article you need hands-on unit-testing experience in c# with Machine.Specifications.

Mocking is not easy always

Most often when we are writing unit test, we are stuck with some not-virtual method which could not be easily mocked. Through this article, I am trying to explain how could we achieve this by below code snippet.

Consider a situation when we want to upload a file to AWS (Amazon Web Services) S3 location,  we are using AWS SDK which exposes a TransferUtility class, a simple API for uploading content to S3.
This blocks of code should be used to upload files to S3 location and this.clientFactory.Get(request.AwsIdentifier) method return and AmazonS3 object. Here if you closely look into the uploader object, this is instantiated by TransferUtility class with a constructor which receive a signature of AmazonS3.
    public class Uploader : IUploader
    {
        public Uploader(IClientFactory clientFactory)
        {
            this.clientFactory = clientFactory;
        }
        
        private readonly IClientFactory clientFactory;
        
        public async Task<string> Upload(UploadRequest request)
        {
            using (var client = await this.clientFactory.Get(request.AwsIdentifier))
            {
                using (var uploader = new TransferUtility(client))
                {
                    if(uploader == null)
                    {
                        throw new ArgumentException("Uploader is required", "fileLocation");
                    }
                    var awsRequest = new TransferUtilityUploadRequest
                    {
                        BucketName = request.BucketName,
                        Key = path,
                        FilePath = request.FileLocation,
                     };

                    await uploader.UploadAsync(awsRequest);
                }

                return request.BucketName + request.FileLocation;
            }
        }
    }

Points of Interest

If we need to write a unit test for method uploader.UploadAsync(awsRequest) to check this method received the valid value which we provided by calling Upload(UploadRequest request).
    [Subject(typeof(Uploader))]
    public abstract class When_upload_a_file
    {
        Establish context = () =>
        {
            s3ClientFactory = Substitute.For<IClientFactory>();
            amazonS3 = Substitute.For<IAmazonS3>();

            uploader = new Uploader(s3ClientFactory);
            
            
            uploadRequest = new UploadRequest
            {
                BucketName = "example-bucket-name",
                AwsIdentifier = "12345",
                FileLocation = "abc.txt"
            };
        };
        
        Because of = async () =>
        {
            response = await uploader.Upload(uploadRequest);
        };

        
        It transferUtility_should_reveive_bucket_name_in_uploader_request =
            () => uploader.Received().Upload(Arg.Is<TransferUtilityUploadRequest>(r => r.BucketName == uploadRequest.BucketName), Arg.Any<CancellationToken>());

        
        
        protected static Uploader uploader;
        protected static IAmazonS3 amazonS3;
        protected static IClientFactory s3ClientFactory;
        
        static UploadRequest uploadRequest;
        static string response;
    }
Complexity arise here!, We could not achieve uploader proxy because uploader objects instantiated by the concrete implementation of TransferUtility class.  TransferUtility doesn't implement an interface and the method I need to mock is not virtual.  that's why we could not mock this object for calling uploader.UploadAsync(awsRequest) method.

How could we achieve this?

If we face like this situation where we are not able to change the external API class, we just need to introduce a wrapper class to avoid concrete class. Below code snippet is an interface and its implementation which have a UploadAsync method with the same signature that contains in UploadAsync method of TransferUtility class. And implemented wrapper class have a constructor which get original TransferUtility object.
 public interface IAwsTransferUtilityWrapper : IDisposable
    {
        Task UploadAsync(TransferUtilityUploadRequest request, CancellationToken cancellationToken = default(CancellationToken));
    }
    public class AwsTransferUtilityWrapper : IAwsTransferUtilityWrapper
    {
        private readonly TransferUtility originalTransferUtility;

        public AwsTransferUtilityWrapper(TransferUtility originalTransferUtility)
        {
            this.originalTransferUtility= originalTransferUtility;
        }

        public async Task UploadAsync(TransferUtilityUploadRequest request, CancellationToken cancellationToken = new CancellationToken())
        {
            await this.originalTransferUtility.UploadAsync(request, cancellationToken);
        }

        public void Dispose()
        {
            this.originalTransferUtility.Dispose();
        }
    }
}

We need to change the instantiation of uploader object in Uploader class as below code snippet
    public class Uploader : IUploader
    {
        public Uploader(IClientFactory clientFactory)
        {
            this.clientFactory = clientFactory;
        }
        
        private readonly IClientFactory clientFactory;
        public static  Func<IAmazonS3, IAwsTransferUtilityWrapper> AwsTransferUtilityFactory { get; set; } = client => new AwsTransferUtilityWrapper(new TransferUtility(client));
        
        public async Task<string> Upload(UploadRequest request)
        {
            using (var client = await this.clientFactory.Get(request.AwsIdentifier))
            {
                using (var uploader = AwsTransferUtilityFactory(client))
                {
                    if(uploader == null)
                    {
                        throw new ArgumentException("Uploader is required", "fileLocation");
                    }
                    var awsRequest = new TransferUtilityUploadRequest
                    {
                        BucketName = request.BucketName,
                        Key = path,
                        FilePath = request.FileLocation
                    };

                    await uploader.UploadAsync(awsRequest);
                }

                return request.BucketName + request.FileLocation;
            }
        }
    }
Now we can test our uploader.UploadAsync(awsRequest) method as like below unit test.
    [Subject(typeof(Uploader))]
    public abstract class When_upload_a_file
    {
        Establish context = () =>
        {
            originalTransferUtilityFactory = Uploader.AwsTransferUtilityFactory;
            transferUtility = Substitute.For<ITransferUtilityWrapper>();
            
            s3ClientFactory = Substitute.For<IClientFactory>();
            amazonS3 = Substitute.For<IAmazonS3>();

            Uploader.AwsTransferUtilityFactory = _ => transferUtility;
            uploader = new Uploader(s3ClientFactory);
            
            
            uploadRequest = new UploadRequest
            {
                BucketName = "example-bucket-name",
                AwsIdentifier = "12345",
                FileLocation = "abc.txt"
            };
        };
        
        Because of = async () =>
        {
            response = await uploader.Upload(uploadRequest);
        };

        
        It transferUtility_should_reveive_bucket_name_in_uploader_request =
            () => uploader.Received().UploadAsync(Arg.Is<TransferUtilityUploadRequest>(r => r.BucketName == uploadRequest.BucketName), Arg.Any<CancellationToken>());

        
        
        protected static Uploader uploader;
        protected static IAmazonS3 amazonS3;
        protected static IClientFactory s3ClientFactory;
        protected static IAwsTransferUtilityWrapper transferUtility;
        static Func<IAmazonS3, IAwsTransferUtilityWrapper> originalTransferUtilityFactory;
        
        static UploadRequest uploadRequest;
        static string response;
    }
Now we are able to  mock a method of external API class by imploementing a wrapper class 'AwsTransferUtilityWrapper'.

Monday, January 18, 2016

Manage Entity Framework Code First Migration in Version Control Environment

How to merge and manage Entity Framework code first migration, when a different team work on the same application with a source control environment.

Introduction

I know there are several articles on Entity Framework Code First approach. But This article intended for those, who face problem to execute Update-Database command in entity framework  after merging the different branch with the change in the same domain object.

Background

There are many contents available in the web to demonstrate how Entity Framework Code First work and I assumes you know that and this is the prerequisite to grab the abstract of this article. If you don't then you can dig into the links:
So I'd not like to re-invent above. This tutorial may assist when you face problem to execute Update-Database command in Package Manage Console.
When we manage a source repository and work in a different team, Entity Framework may cause a problem when two developer change in same domain object in their local code base and Add-Migration to local database and then push code to remote branch.
I'll demonstrate how to generate above situation step by step and how we can resolved it.

Scenario to generate migration problem

Considering that, In a development team, team 'X' works on his local code base with local database and team 'Y' also work on his local code base and local database. Team 'X' add a column to a domain object "Student" and add-migration '***_Address column added to student table' and update-database in locally. On the other hand Team 'Y' also add a column to same "Student" domain object and add-migration '***_EnrollmentDate column added to student table' and update-database locally.
Change By Different Team
Now team 'X' commit their local change and push to remote repository. And team 'Y' take a pull from the remote branch and get all changes that are done by team 'X' and resolved the conflict.

Points of Interest

Now when team 'Y' build the solution and try to execute command 'Update-Database' in package manager console. Stop! for a while and see what happen. All database change is done perfectly but package manager console shown bellow message:
Console Message.
This is because Entity Framework notice that domain model snap shot has been changed by pulling and merging code base from remote branch.

How could we handle this situation

It's time to add a blank migration to update snap shot of current domain model for team 'Y'. To add a blank migration team 'Y' need to add 'IgnoreChanges' attibute in package manager console. One more things, team 'Y' need to consider a name for this migration which was never used in this solution.
Blank migration
Now execute Update-Database command in package manager console and everything is done to handle this situation. Now time to commit and push this code to remote branch, So that other team could use this code base without any hastle.

A Deep Dive into Computed Columns in Entity Framework Core

Entity Framework Core (EF Core) is a popular Object-Relational Mapping (ORM) framework that simplifies database access for .NET applications...