我该如何模拟这个静态方法

Mr.*_*ous 10 c# moq

我有这个代码:

public static bool IsValidVoucher(string id)
{
    //read tsv files
    var temp1 = AppData.GetAppData("stringval");            
    // code that need to be tested        
    return true;        
}
Run Code Online (Sandbox Code Playgroud)

我喜欢创建单元测试,但是如何模拟AppData.GetAppData("stringval")我想要的值,所以我可以测试其余的代码.

AppData类是:

public class AppData
{
    public static object GetAppData(string name)
    {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

rex*_*ghk 6

静态方法不能以简单的方式进行模拟.你基本上有两个选择:

  1. 如果您拥有AppData该类,请更改实现以实现接口(例如IAppData)并删除方法static上的修饰符,GetAppData以便您可以模拟它.

    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");
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果您不拥有AppData该类,请使用AppDataWrapper实现接口的包装类(例如)并从而调用该方法IsValidVoucher:

    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");
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

然后,您可以Foo使用Moq 进行单元测试(在此处使用xunit作为示例):

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
    }
}
Run Code Online (Sandbox Code Playgroud)