在.net反射中使用mock
本文关键字:mock net 反射 | 更新日期: 2023-09-27 18:19:17
我试图在一些反射上尝试嘲笑(下面的代码)。我已经被建议使用nsubstitute,但我正在努力如何实现这一点,并让它开始。
目前,我的测试存根就像下面这样简单,但是在构建服务器上,这些显然失败了,因为dll不存在。
[TestMethod]
public void CanGetStudentXml()
{
var student = new ReadStudent();
var results = student.GetStudentXml();
Assert.AreNotEqual(string.Empty, results);
}
谁能给我指点一下我应该怎么做这件事?我需要创建模拟程序集吗?如果是这样,基于下面的问题,我该如何实现呢?
还有,nsubstitute是最适合这份工作的,还是moq更适合?哪一个是最好的mock框架?
示例代码:
namespace MokPoc
{
using System.Reflection;
using System;
using System.Linq;
class Program
{
static void Main(string[] args)
{
var students = new ReadStudent();
var results = students.GetStudentXml();
var contacts = students.GetTelephoneXml();
}
}
public enum ReflectedAssembyType
{
SimsProcessesTpPersonStudent,
SimsProcessesTpPersonContact
}
internal class ReflectedAssemblyFactory
{
public static ReflectedAssemblyBase GetReflectedAssembly(ReflectedAssembyType reflectedAssembyType)
{
ReflectedAssemblyBase value = null;
switch (reflectedAssembyType)
{
case ReflectedAssembyType.SimsProcessesTpPersonStudent:
value = new SimsProcessesTpPersonStudent("ThirdPartyProcesses.dll");
break;
case ReflectedAssembyType.SimsProcessesTpPersonContact:
value = new SimsProcessesTpPersonContact("PersonContacts.dll");
break;
}
return value;
}
}
internal abstract class ReflectedAssemblyBase
{
private string path = string.Empty;
private string type = string.Empty;
public string Path
{
get { return this.path; }
set { this.path = value; }
}
public string Type
{
get { return this.type; }
set { this.type = value; }
}
public object InvokeFunction(string name, object[] args)
{
var assemblyToLoad = Assembly.LoadFrom(this.path);
var typeToLoad = assemblyToLoad.GetType(this.type);
var methodToInvoke = typeToLoad.GetMethod(name, args.Select(o => o.GetType()).ToArray());
object obj = Activator.CreateInstance(typeToLoad);
return methodToInvoke.Invoke(obj, args);
}
}
internal sealed class SimsProcessesTpPersonStudent : ReflectedAssemblyBase
{
public SimsProcessesTpPersonStudent(string assembly)
{
this.Path = System.IO.Path.Combine(@"C:'Program Files'Zoosk", assembly);
this.Type = "SIMS.Processes.TPPersonStudent";
}
}
public class ReadStudent
{
public string GetStudentXml()
{
var contacts = ReflectedAssemblyFactory.GetReflectedAssembly(ReflectedAssembyType.SimsProcessesTpPersonStudent);
return (string)contacts.InvokeFunction("GetXmlStudents", new object[] { DateTime.Today });
}
public string GetTelephoneXml()
{
var contacts = ReflectedAssemblyFactory.GetReflectedAssembly(ReflectedAssembyType.SimsProcessesTpPersonContact);
return (string)contacts.InvokeFunction("GetXmlTelephone", new object[] { DateTime.Today });
}
}
}
我有重构你的代码理解你试图测试,好像你有很多类的东西看起来可能是一个类的责任,的心在GetStudentAttributes你正在试图做的是,我将创建一个与一个类和公共方法,它返回test.dll一些字符串,然后运行一个实际的方法来测试,在这种情况下,你不使用存根或模仿,但它是一个有效的测试,以确保您的代码工作。你也应该测试GetTelephoneXml和GetStudentXML,但你真正测试的唯一的事情是,GetStudentAttributes是涉及到适当的参数,所以当GetStudentXML被调用你invokeGetStudentAttributes与"ThirdpartyProcesses.dll"answers"GetXmlStudents"。
取决于你使用的解决方案测试框架会不同,Rhynomocks你将不得不做出虚拟允许代理继承和方法调用的方法,但你可以测试参数的方法被称为和你有着什么样子的期盼,我没有用过nSubstitute,所以不知道怎么做,但如果框架是体面的你应该可以测试这些调用和参数。
在使用驱动开发时,你应该做的第一件事就是首先编写测试,确保它失败,让它通过并重构,通常当你试图对现有代码进行测试时,它可能会变得非常困难,有一些关于单元测试的好资源,这是一本很棒的书http://www.amazon.com/Test-Driven-Development-By-Example/dp/0321146530。但根据我的经验,当某些东西很难测试时,它通常告诉你,你的代码太复杂了,或者有些东西可以改进,一旦代码被简化或修复,测试通常不是问题。
祝你好运,希望这对你有所帮助!using System;
using System.IO;
using System.Linq;
using System.Reflection;
namespace MokPoc
{
internal class Program
{
private static void Main(string[] args)
{
var students = new ReadStudentsService();
string results = students.GetStudentXml();
string contacts = students.GetTelephoneXml();
}
}
public class ReadStudentsService
{
private const string ProgramFilesZooskDirectory = @"C:'Program Files'Zoosk";
private const string SimsProcessesTppersonstudent = "SIMS.Processes.TPPersonStudent";
public string GetStudentXml()
{
return GetStudentAttributes("ThirdPartyProcesses.dll", "GetXmlStudents");
}
public string GetTelephoneXml()
{
return GetStudentAttributes("ThirdPartyContacts.dll", "GetXmlTelephone");
}
public string GetStudentAttributes(string dllToUse, string methodToExecute)
{
var fullpath = Path.Combine(ProgramFilesZooskDirectory, dllToUse);
var args = new object[] {DateTime.Today};
var assemblyToLoad = Assembly.LoadFrom(fullpath);
var typeToLoad = assemblyToLoad.GetType(SimsProcessesTppersonstudent);
var methodToInvoke = typeToLoad.GetMethod(methodToExecute, args.Select(o => o.GetType()).ToArray());
var obj = Activator.CreateInstance(typeToLoad);
return (string) methodToInvoke.Invoke(obj, args);
}
}
}