I have this code:
public static bool IsValidVoucher(string id)
{
//read tsv files
var temp1 = AppData.GetAppData("stringval");
// code that need to be tested
return true;
}
And I like to create unit test, but how can I mock AppData.GetAppData("stringval")
to whatever I want the value is, so I can test the rest of code.
The AppData class is:
public class AppData
{
public static object GetAppData(string name)
{
//...
}
}
Mocking Static Classes, Methods, and Properties Overview The difference between the two classes is that a static class cannot be instantiated. The new operator cannot create a variable of the class type. Because there is no instance variable, the class name itself should be used to access the members of a static class.
mock() method with Answer: It is used to create mock objects of a class or interface with a specific procedure. It is an advanced mock method, which can be used when working with legacy systems. It takes Answer as a parameter along with the class or interface name.
Static methods cannot be mocked in an easy way. You basically have two choices:
If you own the AppData
class, change the implementation to implement an interface (e.g. IAppData
) and remove the static
modifier on the GetAppData
method so you can mock it.
public interface IAppData
{
object GetAppData(string id);
}
public class AppData : IAppData
{
public object GetAppData(string id) {}
}
public class Foo
{
private readonly IAppData _appData;
public Foo(IAppData appData)
{
_appData = appData;
}
public bool IsValidVoucher(string id)
{
// Call through object instance instead for class reference
var temp1 = _appData.GetAppData("stringval");
}
}
If you do not own the AppData
class, use a wrapper class (e.g. AppDataWrapper
) that implements an interface and call that method from IsValidVoucher
instead:
public interface IAppData
{
object GetAppData(string id);
}
public class AppDataWrapper : IAppData
{
public object GetAppData(string id)
{
return AppData.GetAppData(id);
}
}
public class Foo
{
private readonly IAppData _appData;
public Foo(IAppData appData)
{
_appData = appData;
}
public bool IsValidVoucher(string id)
{
var temp1 = _appData.GetAppData("stringval");
}
}
You can then unit test Foo
using Moq (using xunit as an example here):
public class FooTests
{
private readonly IAppData _mockAppData;
public FooTests()
{
var mockAppData = new Mock<IAppData>();
mockAppData.Setup(m => m.GetAppData(It.IsAny<string>)).Returns("my test value");
_mockAppData = mockAppData.Object;
}
[Fact]
public void IsValidVoucher_ValidAppData_Returns()
{
var foo = new Foo(_mockAppData);
// Unit test foo.IsValidVoucher
}
}
Well, I think everyone's comments so far is technically correct - using something like RhinoMocks
or Moq
, you really can't mock static methods in a facile, straightforward manner.
But using Moles
, you definitely can. So if you have significant (currently) untestable code that reside within static methods, I think you should be looking into Moles.
(This link is a bit dated but I still find it helpful) http://research.microsoft.com/en-us/projects/pex/molesmanual.pdf
(Key text)
Moles can be used to detour any .NET method, including non-virtual and static methods in sealed types.
How it works: Suppose you have a typical situation like this:
public static class SomeStaticClass
{
public static int SomeStaticMethod(string s)
{
return "Static method called: " + s;
}
}
public class SomeInstanceClass
{
public string SomeInstanceMethod(string s)
{
return SomeStaticClass.SomeStaticMethod(s);
}
}
Using Moles, your test code would look like this:
[TestMethod()]
[HostType("Moles")]
public void ShouldBeAbleToTestStaticMethod()
{
var instance = new SomeInstanceClass();
var testValue = instance.SomeInstanceMethod("Some test string");
SomeStaticClass.SomeStaticMethod = (s) => "Moled you! " + s;
Assert.That(testValue, Is.EqualTo("Moled you! Some test string"); // sorry, this has code smell, lol
}
Of course you need to set up Moles into your test project, so be sure to look it up - lots of web resources to help you on your way.
Some helpful posts:
https://msdn.microsoft.com/en-us/library/ff798308.aspx
http://adventuresdotnet.blogspot.com/2011/03/mocking-static-methods-for-unit-testing.html
https://wannabeegeek.wordpress.com/2013/03/13/unit-testing-made-easy-with-moles-part-i/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With