Home » Softwares » Visual Studio » How to unit test a method that is not from an interface, neither virtual with Visual Studio 2012

How to unit test a method that is not from an interface, neither virtual with Visual Studio 2012

Microsoft has the ability to fake method but as the disadvantage that it requires to be from an interface or to be virtual. This is the case of most testing framework. Nevertheless, Microsoft has the principle of Shim which allow to replace the method behavior by yours for the time of a test. You can get additional information on MSDN. This blog article explains briefly how to use shim.

For the purpose of this article, let say that we have a library with a single class which contain a single method :

namespace ShimpProjectClassesToShim
{
    public class MyClass
    {
        public string MyMethod(string variable)
        {
            return "From MyClass = " + variable;
        }
    }
    public class MyClass2
    {
        public string ToTest()
        {
            var m = new MyClass();
            return m.MyMethod("InsideMyClass2");
        }
    }
}

This method is not virtual, but could have been because shim can be bound to static method. As you can see, the purpose of the test would be to change the inside of the method for the time of a test method.

To continue with our example, we need a second project, the one of the test. This one will have a reference to the library previously created. Once done, right click the reference and click “Add Fake Assembly“.

AddFakesAssembly

Do no worry, you have already added the reference from the unit project to the library project. Maybe a better naming of the action should have been “Transform to Fake Assembly. When done, you will see a Fakes folder created with the fake reference.

fakesFolder

If you are curious about what contain this file, here is the one of the example :

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="ShimpProjectClassesToShim"/>
</Fakes>

So the test will consist of shimming MyClass that is used by MyClass2. This is a common scenario that you want to test a method that use an other class that you do not want to test. In our case, we want to test MyClass2 and not MyClass, we shim MyClass to have a known return value.

The test my be inside the scope of a ShimContext to be able to set the shim inside the test.

[TestClass]
public class UnitTest1
{
	[TestMethod]
	public void TestMethod1()
	{
		//Shim
		using (ShimsContext.Create())
		{
			//Arrange
			ShimMyClass.AllInstances.MyMethodString = (theClass, s) => "FAKE " + s;
			var classToUnitTest = new MyClass2();

			//Act
			string result = classToUnitTest.ToTest();

			//Assert
			Assert.AreEqual("FAKE InsideMyClass2", result);
		}
	}
}

The arrange section set for all instances of the method the desired return value. As you can see we use “ShimMyClass” class to set all instances. In your case, if you class is called “XYZ”, you will have to use “ShimXYZ”. This is by design that a class has been created for you with the prefix Shim. From there, you will be able to set return value for all methods. The rest of the unit test is as usual.

If you like my article, think to buy my annual book, professionally edited by a proofreader. directly from me or on Amazon. I also wrote a TypeScript book called Holistic TypeScript

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.