简体   繁体   中英

How can I mock this static method

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)
    {
        //...
    }
}

Static methods cannot be mocked in an easy way . You basically have two choices:

  1. If you own the AppData class, change the implementation to implement an interface (eg 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"); } } 
  2. If you do not own the AppData class, use a wrapper class (eg 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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM