Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing a method that uses an external dll

I have a project named A that has a class named ClassA. ClassA has a method named ReadBlock() which creates a CloudBlockBlob object and calls one of its methods.

CloudBlockBlob is a class which is located in Microsoft.WindowsAzure.Storage.Blob namespace which is in Microsoft.WindowsAzure.Storage.dll.

My project A has a unit testing project named A.Tests. Now, I want to test method ReadBlock(). To test it, I need to mock the CloudBlockBlob object and intercept the calls to its methods, return custom values and verify that the methods were called.

  • How can I mock an object that is fully created inside a method?
  • Can I somehow change project A's dll reference and reference it to a mock dll that creates a mock object instead the real one?
  • Can I override project A's call for classes inside the Microsoft.WindowsAzure.Storage.Blob with an implementation of my own in A.Tests class?

UPDATE: The question is whether I can do this without modifying project A's code.

Thanks!

like image 827
shlatchz Avatar asked May 30 '26 19:05

shlatchz


1 Answers

Without modifing class A code you won't be able to UT the ReadBlock method using Moq. You'll be able to UT this method using code weaving tools (MsFakes, Typemock Isolator, etc...)

For example(MsFakes):

[TestMethod]
public void TestMethod1()
{
    using (ShimsContext.Create())
    {
        ShimCloudBlockBlob.AllInstances.<the method you want to override>  = (<the method arguments>) => {};
    }
}

Inside the using scope you'll be able to override any method CloudBlockBlob has, through the property AllInstances.

In the next section I'm going to discuss all the other options you have...

Option 1:

    public class A
    {
        private IBlockBlob _blockBlob;

        public A(IBlockBlob blockBlob)
        {
            _blockBlob = blockBlob;
        }

        public void ReadBlock()
        {
            _blockBlob.DoSomething();
        }
    }

Since you create a new instance each time call ReadBlock(your method's current behavior) you better inject a factory instead of wrapper and DoSomething should be create; Option 2:

    public class A
    {
        private readonly IFactoryBlockBlob _blobFctory;

        public A(IFactoryBlockBlob blobFctory)
        {
            _blobFctory = blobFctory;
        }

        public void ReadBlock()
        {
           var blob =  _blobFctory.Create();
        }
    }

However, based on your question and your comments it seems that your class 'has a dependency' instead of 'needs a dependency'.

enter image description here

(Mark Siemens wrote a great book about DI, this chart was taken from his book)

With this new piece of information your method should be something like; Option 3:

    public class A
    {
        public void ReadBlock(ICloudBlob blob)
        {
        }
    }

But you don't want to change the signature of the method:

    public class A
    {

        public void ReadBlock()
        {
            ReadBlock(new CloudBlockBlob(<the params bla bla...>));
        }

        internal void ReadBlock(ICloudBlob blob)
        {
        }
    }

Add InternalsVisibleToAttribute, then verify the behavior of the internal method.

By reading between the lines, it feels to me that your class is a kind of "legacy code" meaning that it can do the job, won't change, and verifying its behavior might be a waste of time. In the past I've posted a chart (in this answer) which may help you to decide the way to handle this case.

like image 80
Old Fox Avatar answered Jun 02 '26 09:06

Old Fox