Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何模拟这种静态方法_C#_Moq - Fatal编程技术网

C# 如何模拟这种静态方法

C# 如何模拟这种静态方法,c#,moq,C#,Moq,我有以下代码: public static bool IsValidVoucher(string id) { //read tsv files var temp1 = AppData.GetAppData("stringval"); // code that need to be tested return true; } 我喜欢创建单元测试,但是如何模拟AppData.GetAppData(“string

我有以下代码:

public static bool IsValidVoucher(string id)
{
    //read tsv files
    var temp1 = AppData.GetAppData("stringval");            
    // code that need to be tested        
    return true;        
}
我喜欢创建单元测试,但是如何模拟
AppData.GetAppData(“stringval”)
到我想要的值,以便测试其余的代码

AppData类是:

public class AppData
{
    public static object GetAppData(string name)
    {
        //...
    }
}

静态方法不能简单地模仿。您基本上有两种选择:

  • 如果您拥有
    AppData
    类,请将实现更改为实现接口(例如
    IAppData
    ),并删除
    GetAppData
    方法上的
    static
    修饰符,以便可以对其进行模拟

    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");
        }
    }
    
  • 如果您不拥有
    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");
        }
    }
    
  • 然后,您可以使用Moq进行单元测试
    Foo
    (这里以xunit为例):

    公共级足球鞋
    {
    私有只读IAppData\u mockAppData;
    公共足球()
    {
    var mockAppData=new Mock();
    Setup(m=>m.GetAppData(It.IsAny)).Returns(“我的测试值”);
    _mockAppData=mockAppData.Object;
    }
    [事实]
    public void IsValidVoucher_validapdata_Returns()
    {
    var foo=新foo(_mockAppData);
    //单元测试foo.IsValidVoucher
    }
    }
    
    好吧,我认为到目前为止,每个人的评论在技术上都是正确的-使用类似于
    RhinoMocks
    Moq
    的东西,你真的不能简单、直接地模拟静态方法

    但是使用
    摩尔
    ,你绝对可以。所以,如果您有大量(当前)不稳定的代码驻留在静态方法中,我认为您应该研究Moles

    (此链接有点过时,但我仍然觉得它很有用)

    (主要文本)

    Moles可以用于绕过任何.NET方法,包括密封类型中的非虚拟和静态方法

    工作原理:假设您有这样一个典型情况:

    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);
        }
    }
    
    [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
    }
    
    使用Moles,您的测试代码如下所示:

    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);
        }
    }
    
    [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
    }
    
    当然,你需要在你的测试项目中设置Moles,所以一定要查找它——大量的网络资源可以帮助你

    一些有用的帖子:


    不必硬编码“AppData.GetAppData”,您可以插入一个读取AppData的类,然后在单元测试中模拟该类并设置所需的返回值。如果不进一步更改源代码,则不可能使用Moq。但有了它是可能的。然而,隔离器不是免费的。还有一些关于模拟静态方法的更多信息。然后回答。我放弃了我的答案,因为我相信它在这种情况下不会有帮助。不管怎样,现在你知道表达式树是有很大帮助的!你说过静态方法不能被模仿。。。看看我的答案;P也许这是一个疯狂的想法,但它奏效了@MatíasFidemraizer,我应该说静态方法不能轻易地被模仿;)为Clarity编辑我认为你至少应该在你的答案中展示一些代码,展示Moles如何帮助单元测试静态方法,而不是简单地发布到各种资源的链接。Moles仍然受支持/可用吗?该网站似乎表示,赝品将取代它,而可推测的下载链接只会将我指向一个没有鼹鼠的列表。我可能错过了下载链接?以下是MS Fakes的最新(VS 2017)文档:不幸的是,Fakes仅在Visual Studio的企业SKU中提供:对于Moles,似乎它最后一次受到支持是在VS 2010中: