Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net Fakes - How to shim an inherited property when the base class is abstract?

I am trying to write a unit test that covers the following line

var fileFullName = fileInfo.FullName;

where fileInfo is an instance of FileInfo.

I am using fakes to shim the FileInfo object, but I am unable to provide a value for the FullName property, because it is inherited from the base class.

For the Name property, which is not inherited, I can simply do this:

ShimFileInfo.AllInstances.NameGet = info => OriginalFullName;

The answer provided by Microsoft is to create the shim on the base class, in this case FileSystemInfo. But if I try this:

ShimFileSystemInfo.AllInstances.FullNameGet = info => OriginalFullName;

It does not work, because FileSystemInfo is an abstract class which cannot be created and therefore cannot be shimmed.

In this particular case, I can get around it because I can combine the DirectoryName and Name properties to make it testable, but it seems crazy that I can't just use the property I want because it happens to come from the base.

Has anyone come accross this problem and managed to solve it?

like image 489
lextechnica Avatar asked Apr 09 '14 12:04

lextechnica


1 Answers

You said that shimming the base class didn't work, but I do exactly that and it works in our tests.

FileInfo in System.dll is defined as FileInfo : FileSystemInfo, and FileSystemInfo is in mscorlib. Many types in mscorlib are not shimmed by default, but if you add this to your mscorlib.fakes file:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="mscorlib" Version="4.0.0.0"/>
  <ShimGeneration>
    <Add FullName="System.IO.FileSystemInfo"/>
  </ShimGeneration>
</Fakes>

and then build your test project you get a ShimFileSystemInfo for FileSystemInfo from mscorlib, as well as the ShimFileInfo for FileInfo from System.dll. Then this works:

using (ShimsContext.Create())
{
    var directoryName = "<testPath>";
    var fileName = "test.txt";
    ShimFileSystemInfo.AllInstances.FullNameGet = @this => "42";
    result = new DirectoryInfo(directoryName).GetFiles(fileName).First();
    Assert.AreEqual("42", result.FullName);   // the fake fullname
    Assert.AreEqual("test.txt", result.Name); // the real name
}

Caveat: works on my machine (Visual Studio 2013, .NET 4.5.1)

Reference for the fakes file: Code generation, compilation, and naming conventions in Microsoft Fakes

like image 81
Andy Brown Avatar answered Oct 22 '22 16:10

Andy Brown