外部服务的单元测试
本文关键字:单元测试 服务 外部 | 更新日期: 2023-09-27 17:49:43
我想对一个使用外部依赖项的函数进行单元测试。
方法如下:
public string GetUrl(string records = "")
{
if (records.IsNullOrEmpty())
{
records = Partner.Current["Records"];
}
return string.Format(
"http://{0}/{1}?pid={2}",
recordsdomain,
HttpUtility.UrlEncode(FullName
.Replace(' ', '_')
.Replace("''", string.Empty)
.Replace("?", string.Empty)),
Id);
}
这个方法位于一个类中,该类有如下构造函数:
public Person(Person person)
{
FullName = person.firstname + person.lastname
}
问题是:Person没有公共构造函数,这就是为什么它不允许为它创建mock的原因。
person对象是如何生成的:
Person person = Service.GetPerson(Guid.Empty, "115763963", 1);
如何解决这个问题?
外部服务创建person对象并从其数据库提供对象。此外,对象是在外部服务上声明的,因此我不能只是创建它的新实例并将信息提供给它。
您需要使用模拟技术。您将创建一个mock person对象,该对象返回名字和姓氏属性的固定值。然后可以将模拟人传递给构造函数。
根据您选择的模拟框架,代码看起来会有所不同。使用Moq,它看起来像这样:
var person = new Mock<Person>();
person.SetupGet(p => p.firstname).Returns("Joe");
person.SetupGet(p => p.firstname).Returns("Smith");
// your mock person does now return names for testing
// and you can pass it to the constructor
如果外部服务功能可以被认为是理所当然的,您总是可以伪造它(有点负担,但是如果您只需要数据来测试其他代码,它可能是可行的)。
Person person = Service.GetPerson(Guid.Empty, "115763963", 1);
将成为
Person person = FakeService.GetPerson(Guid.Empty, "115763963", 1);
在这里你会有像
这样的东西public static class FakeService
{
public static Person GetPerson(Guid foo, string bar, int baz)
{
Person something = new Person{ /*Put nice data here*/ };
return something;
}
}
可能很粗糙,但如果您只需要该服务为您提供一些数据来使用,那么应该可以使用。如果您还需要测试服务本身,那么这种方法显然是无意义的。
更新:由于Person
的向量是不可访问的,为了这种方法的工作,你也必须伪造它…要立即检查的一件事是,如果Person
是partial
类,您可能能够将其拉下来,只需添加一个新actor即可(需要尝试,因为我做了这样的事情已经有一段时间了):
public partial class Person
{
public Person(){}
}
我使用这种方法来扩展自动生成的数据上下文类,它可能也适用于您。
不那么严重的是,你也可以要求在这个类中添加一个公共变量重载!