C# 包装静态类/方法以便对其进行单元测试?
我有一个用于日志记录的静态类:C# 包装静态类/方法以便对其进行单元测试?,c#,.net,unit-testing,nunit,moq,C#,.net,Unit Testing,Nunit,Moq,我有一个用于日志记录的静态类: public static class myLogger { public static ErrorLogging(string input) { //dostuff } } 我使用它的方式是: public class myClassthatDoesStuff { ... myLogger.ErrorLogging("some error ocurred"); ... } 我怎样才能禁用myLo
public static class myLogger
{
public static ErrorLogging(string input)
{
//dostuff
}
}
我使用它的方式是:
public class myClassthatDoesStuff
{
...
myLogger.ErrorLogging("some error ocurred");
...
}
我怎样才能禁用myLogger类,以便能够对其进行单元测试并确保执行了ErrorLogging方法是否可以在不设置构造函数中任何参数的情况下执行此操作(构造函数注入)?myClassthatDoesStuff要求构造函数中没有参数。如果无法将其从静态类更改为非静态类,请使用非静态类包装它
void Test()
{
string testString = "Added log";
var logStore = new List<string>();
ILogger logger = new MyTestableLogger(logStore);
logger.ErrorLogging(testString);
Assert.That(logStore.Any(log => log==testString));
}
public interface ILogger
{
void ErrorLogging(string input);
}
public class MyTestableLogger : ILogger
{
public MyTestableLogger(ICollection<string> logStore)
{
this.logStore = logStore;
}
private ICollection<string> logStore;
public void ErrorLogging(string input)
{
logStore.Add(input);
MyLogger.ErrorLogging(input);
}
}
public static class MyLogger
{
public static void ErrorLogging(string input)
{
// Persist input string somewhere
}
}
void测试()
{
string testString=“添加日志”;
var logStore=新列表();
ILogger logger=新的MyTestableLogger(logStore);
logger.ErrorLogging(testString);
Assert.That(logStore.Any(log=>log==testString));
}
公共接口ILogger
{
无效错误记录(字符串输入);
}
公共类MyTestableLogger:ILogger
{
公共MyTestableLogger(ICollection logStore)
{
this.logStore=logStore;
}
私人ICollection logStore;
公共无效错误记录(字符串输入)
{
添加(输入);
MyLogger.ErrorLogging(输入);
}
}
公共静态类MyLogger
{
公共静态无效错误记录(字符串输入)
{
//将输入字符串保存到某个位置
}
}
您可以使用Microsoft的
假设您的项目名为ConsoleApplication1
首先,转到单元测试项目引用,右键单击包含
MyClassThatDoesTuff
class的程序集,并选择“添加伪程序集”
使用垫片进行的单元测试如下所示:
[TestClass()]
public class MyClassthatDoesStuffTests
{
[TestMethod()]
public void ImportansStuffTest()
{
using (ShimsContext.Create())
{
bool logCalled = false;
ConsoleApplication1.Fakes.ShimmyLogger.ErrorLoggingString =
(message) => logCalled = true;
new myClassthatDoesStuff().ImportansStuff();
Assert.IsTrue(logCalled);
}
}
}
描述了完全相同的场景-您有一个旧的静态日志记录方法,并且希望在可测试代码中使用它
- 将静态类包装在非静态类中-不仅用于测试,还用于一般用途
- 将新的非静态类的方法提取到接口中
- 无论您在哪里依赖静态类,都应该依赖接口。例如,如果class
需要静态类中的函数,请执行以下操作:DoesMething
public interface ILogger { void ErrorLogging(string input); } public class MyClassthatDoesStuff { private readonly ILogger _logger; public MyClassthatDoesStuff(ILogger logger) { _logger = logger; } }
ILogger
,就像将错误消息添加到列表中的类一样
class StringLogger : List<string>, ILogger
{
public void ErrorLogging(string input)
{
Add(input);
}
}
var testSubject = new MyClassthatDoesStuff(new StringLogger());
class StringLogger:列表,ILogger
{
公共无效错误记录(字符串输入)
{
添加(输入);
}
}
var testSubject=new myclassthattowestuff(new StringLogger());
[TestMethod]
public void TestLogging()
{
//Arrange
Isolate.WhenCalled(() => myLogger.ErrorLogging("")).CallOriginal();
//Act
var foo = new myClassthatDoesStuff();
foo.DoStuff();
//Assert
Isolate.Verify.WasCalledWithAnyArguments(() => myLogger.ErrorLogging(""));
}
查看Microsoft的填隙片要求Visual Studio Ultimate,它可能是Moles的复制品,它仍然适用于VS2010-是否可以不在构造函数中设置任何参数就执行此操作(构造函数注入)?myClassthatDoesStuff要求构造函数中没有参数。如果你不能在构造函数中放入任何东西,那肯定会使它更难。如果您可以从头开始使用依赖项注入,从而可以控制类的实例化方式。例如,如果没有依赖项注入,WCF服务类的构造函数中通常不会有任何内容。scott非常感谢您对这一切的解释。有意义无需在构造函数中设置任何参数(构造函数注入)就可以做到这一点吗?myClassthatDoesStuff要求构造函数中没有参数。@l--“l”--“l”--“l”(不知道
@
提到的内容可能会变成这样的折磨…)您可以删除参数确定。。。但是,如何测试您添加的日志条目是否存在于数据存储中呢?:)