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");
}
}
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中: