外部服务的单元测试

本文关键字:单元测试 服务 外部 | 更新日期: 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的向量是不可访问的,为了这种方法的工作,你也必须伪造它…要立即检查的一件事是,如果Personpartial类,您可能能够将其拉下来,只需添加一个新actor即可(需要尝试,因为我做了这样的事情已经有一段时间了):

public partial class Person
{
    public Person(){}
}

我使用这种方法来扩展自动生成的数据上下文类,它可能也适用于您。

不那么严重的是,你也可以要求在这个类中添加一个公共变量重载!