Moles does not work in static constructors
I have been having a problem with Mole types not working in static constructors. I have created two simple examples to explain the problem:
I have a simple instance class as follows:
public class InstanceTestReader
{
public InstanceTestReader ()
{
IFileSystem fileSystem = new FileSystem();
this.Content = fileSystem.ReadAllText("test.txt");
}
public string Content { get; private set; }
}
I have a unit test for this as follows:
[TestMethod]
[HostType("Moles")]
public void CheckValidFileInstance_WithMoles()
{
// Arrange
string expectedFileName = "test.txt";
string content = "test text content";
Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) =>
{
Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect");
return content;
};
// Act
string result = new InstanceTestReader().Content;
// Assert
Assert.AreEqual(content, result, "The result was incorrect");
}
This works with no problems.
If I change my calling class to be static however (NOT the Moled class, but the calling class), Moles no longer works:
public static class StaticTestReader
{
static StaticTestReader ()
{
IFileSystem fileSystem = new FileSystem();
Content = fileSystem.ReadAllText("test.txt");
}
public static string Content { get; private set; }
}
And modify my unit test accordingly:
[TestMethod]
[HostType("Moles")]
public void CheckValidFileStatic_WithMoles()
{
// Arrange
string expectedFileName = "开发者_C百科test.txt";
string content = "test text content";
Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) =>
{
Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect");
return content;
};
// Act
string result = StaticTestReader.Content;
// Assert
Assert.AreEqual(content, result, "The result was incorrect");
}
... Now Moles no longer works. When running this test, I get the error "Could not find file 'd:\blah\blah\test.txt'". I get this because Moles is no longer in charge of my FileSystem class, so the unit test is calling the original implementation which is looking for a file on the file system.
So, the only change is that the class which the Moled method is called from is now static. I have not changed the Moled class or method, they are still instance types, so I cannot use the Implementation.Moles.SFileSystem syntax as this would be for mocking a static class.
Please could someone help to explain how I can get Moles to work within a static method/constructor?
Many thanks!!!
A static constructor is different than a static method. With a method you have control of when and where its called. The constructor is automatically called by the runtime before any access to the class is performed which in this case leads to the constructor being called before the mole for the FileSystem
is set up resulting in the error you are seeing.
If you change your implementation to something like the following then it should work.
public static class StaticTestReader
{
private static string content;
public static string Content
{
get
{
if (content == null)
{
IFileSystem fileSystem = new FileSystem();
content = fileSystem.ReadAllText("test.txt");
}
return content;
}
}
}
Update:
However, if you cannot change your implementation the only other alternative that Moles offers is for you to prevent the code in the static constructor to be executed and then mole the Content
property directly. To erase a static constructor for a type you need to include the following assembly level attribute in your test assembly:
[assembly: MolesEraseStaticConstructor(typeof(StaticTestReader))]
I think you have to remove the AllInstances from your declaration. To access the static you do not need an instance of a class.
try this:
Implementation.Moles.MFileSystem.ReadAllTextString = (...)
精彩评论