C# 使用Rhinomock模拟用于单元测试的xml文件
我想模拟用于单元测试的xml,如下所示。我正在使用Rhinomocks框架进行模拟。如何通过不使用实际的xml文件来对我的方法进行单元测试。我必须更改代码结构吗C# 使用Rhinomock模拟用于单元测试的xml文件,c#,xml,unit-testing,rhino-mocks,C#,Xml,Unit Testing,Rhino Mocks,我想模拟用于单元测试的xml,如下所示。我正在使用Rhinomocks框架进行模拟。如何通过不使用实际的xml文件来对我的方法进行单元测试。我必须更改代码结构吗 [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class MyService : IMyService { private readonly string mSchemaPath = Path.Combine(
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyService
{
private readonly string mSchemaPath = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "App_Data",
"schema_0.1.xsd");
private readonly string mXmlPath = Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "App_Data",
"MyDataRecords.xml");
private XDocument mXDocument;
public MyService()
{
try
{
//load xml document
mXDocument = XDocument.Load(mXmlPath);
if (mXDocument == null)
{
throw new Exception("Null returned while reading xml file");
}
}
catch (Exception e)
{
//my exception management code
}
}
public List<MyDataRecords> GetAllRecords()
{
////fetch records from xDocument
mXDocument.Save();
}
public void AddRecord(MyRecord record)
{
////add record
mXDocument.Save();
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
公共类MyService:IMyService
{
私有只读字符串mSchemaPath=Path.Combine(HostingEnvironment.ApplicationPhysicalPath,“应用程序数据”,
“schema_0.1.xsd”);
私有只读字符串mXmlPath=Path.Combine(HostingEnvironment.ApplicationPhysicalPath,“应用程序数据”,
“MyDataRecords.xml”);
私人XDocument文件;
公共MyService()
{
尝试
{
//加载xml文档
mXDocument=XDocument.Load(mXmlPath);
if(mXDocument==null)
{
抛出新异常(“读取xml文件时返回Null”);
}
}
捕获(例外e)
{
//我的异常管理代码
}
}
公共列表GetAllRecords()
{
////从xDocument获取记录
mXDocument.Save();
}
公共无效添加记录(MyRecord)
{
////添加记录
mXDocument.Save();
}
更新:
我已经修改了MyService类,使其具有重载构造函数,它接受Func
来加载XDocument,还接受Func
来解析与HostingEnvironment.ApplicationPhysicalPath
相对应的值。调用默认构造函数时,将执行对XDocument.load的相同调用,类似于se用于在构建xml和xsd文件的路径时使用HostingEnvironment.ApplicationPhysicalPath
但是,在单元测试中,您可以像这样调用其他构造函数:
const string mockDirectory = "TEST";
var expectedXmlPath = Path.Combine(mockDirectory, "App_Data", "MyDataRecords.xml");
string xmlPathPassed = "";
var service = new MyService(path =>
{
xmlPathPassed = path;
return XDocument.Parse("<note><to>Tove</to><from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body></note>");
},
() => mockDirectory);
Assert.Equal(expectedXmlPath, xmlPathPassed);
const string mockDirectory=“TEST”;
var expectedXmlPath=Path.Combine(mockDirectory,“App_Data”,“MyDataRecords.xml”);
字符串xmlPathPassed=“”;
var service=newmyservice(路径=>
{
xmlPathPassed=path;
return XDocument.Parse(“ToveJaniReminderDon’t忘了我这个周末!”);
},
()=>mockDirectory);
等于(expectedXmlPath,xmlPathPassed);
您还可以在服务上公开XDocument,可能是通过只读属性,并检查XDocument是否表示模拟的xml
我的服务:
public class MyService : IMyService
{
private const string AppDataDirectoryName = "App_Data";
private const string SchemaFileName = "schema_0.1.xsd";
private const string XmlFileName = "MyDataRecords.xml";
private readonly Func<string, XDocument> mdocumentLoader;
private readonly Func<string> mAppDataDirectoryBuilder;
private readonly string mSchemaPath = "";
private readonly string mXmlPath = "";
private XDocument mXDocument;
public MyService() : this(XDocument.Load, () => HostingEnvironment.ApplicationPhysicalPath)
{
}
public MyService(Func<string, XDocument> documentLoader, Func<string> appDataDirectoryBuilder)
{
mdocumentLoader = documentLoader;
mAppDataDirectoryBuilder = appDataDirectoryBuilder;
try
{
var baseDirectory = mAppDataDirectoryBuilder();
mSchemaPath = Path.Combine(baseDirectory, AppDataDirectoryName, SchemaFileName);
mXmlPath = Path.Combine(baseDirectory, AppDataDirectoryName, XmlFileName);
mXDocument = mdocumentLoader(mXmlPath);
if (mXDocument == null)
{
throw new Exception("Null returned while reading xml file");
}
}
catch (Exception e)
{
//my exception management code
}
}
public List<MyRecord> GetAllRecords()
{
////fetch records from xDocument
return null;
//mXDocument.Save();
}
public void AddRecord(MyRecord record)
{
////add record
// mXDocument.Save(record);
}
公共类MyService:IMyService
{
私有常量字符串AppDataDirectoryName=“App\u Data”;
私有常量字符串SchemaFileName=“schema_0.1.xsd”;
private const string XmlFileName=“MyDataRecords.xml”;
私有只读Func mdocumentLoader;
私有只读Func mAppDataDirectoryBuilder;
私有只读字符串mSchemaPath=“”;
私有只读字符串mXmlPath=“”;
私人XDocument文件;
public MyService():这(XDocument.Load,()=>HostingEnvironment.ApplicationPhysicalPath)
{
}
公共MyService(Func documentLoader、Func appDataDirectoryBuilder)
{
mdocumentLoader=documentLoader;
mAppDataDirectoryBuilder=appDataDirectoryBuilder;
尝试
{
var baseDirectory=mAppDataDirectoryBuilder();
mSchemaPath=Path.Combine(baseDirectory、AppDataDirectoryName、SchemaFileName);
mXmlPath=Path.Combine(baseDirectory、AppDataDirectoryName、XmlFileName);
mXDocument=mdocumentLoader(mXmlPath);
if(mXDocument==null)
{
抛出新异常(“读取xml文件时返回Null”);
}
}
捕获(例外e)
{
//我的异常管理代码
}
}
公共列表GetAllRecords()
{
////从xDocument获取记录
返回null;
//mXDocument.Save();
}
公共无效添加记录(MyRecord)
{
////添加记录
//mXDocument.Save(记录);
}
}[程序集:InternalsVisibleTo(“MyService.UnitTests”)]
公共类MyService:IMyService
{
私有只读字符串路径;
私有只读字符串mXmlPath;
公共MyService()
:这个(
Combine(HostingEnvironment.ApplicationPhysicalPath,“App_Data”,“MyDataRecords.xml”),
Combine(HostingEnvironment.ApplicationPhysicalPath,“App_数据”,“schema_0.1.xsd”))
{
}
内部MyService(字符串xmlPath、字符串schemaPath)
{
尝试
{
mXmlPath=xmlPath;
mSchemaPath=schemaPath;
//加载xml文档
mXDocument=Xdocument.Laod(mXmlPath);
if(mXDocument==null)
{
抛出新异常(“读取xml文件时返回Null”);
}
}
捕获(例外e)
{
//我的异常管理代码
}
}
公共列表GetAllRecords()
{
////从xDocument获取记录
mXDocument.Save();
}
公共无效添加记录(MyRecord)
{
////添加记录
mXDocument.Save();
}
}这是一个绝妙的建议,在不破坏大部分代码结构的情况下,我可以做到这一点。唯一需要考虑的是,客户端也可以使用其他构造函数。我如何阻止这种情况?这种单元测试方法在将测试改装为遗留代码时非常有用。不过,我还没有找到一种不公开额外构造函数的方法。可测试性p在我的书中,ayoff超过了这个设计问题;始终加载原始xml。我不确定是否正确地跟踪了您。在上面的示例中,mXmlPath始终针对生产和单元测试场景进行初始化,这很好。在单元测试场景中,调用
var service=new MyService(不相关路径=>XDocument.Parse(“用于单元测试的xml”));
,忽略“不相关路径”(mXmlPath)并只解析xml字符串,没有实际加载xml文件。您的单元测试是否加载xml字符串?为什么不简单地将“仅测试”构造函数设置为内部,然后扩展内部,使其可访问
[assembly: InternalsVisibleTo("MyService.UnitTests")]
public class MyService : IMyService
{
private readonly string mSchemaPath;
private readonly string mXmlPath;
public MyService()
: this(
Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "App_Data", "MyDataRecords.xml"),
Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "App_Data", "schema_0.1.xsd"))
{
}
internal MyService(string xmlPath,string schemaPath)
{
try
{
mXmlPath=xmlPath;
mSchemaPath=schemaPath;
//load xml document
mXDocument = Xdocument.Laod(mXmlPath);
if (mXDocument == null)
{
throw new Exception("Null returned while reading xml file");
}
}
catch (Exception e)
{
//my exception management code
}
}
public List<MyRecord> GetAllRecords()
{
////fetch records from xDocument
mXDocument.Save();
}
public void AddRecord(MyRecord record)
{
////add record
mXDocument.Save();
}