使用FakeItEasy伪造单身人士

时间:2017-03-12 14:09:41

标签: c# unit-testing mocking singleton fakeiteasy

我在测试单身时遇到了一些问题。当我运行此代码时,我在TestGetLogicalDevices()中收到错误。 CallTo()失败,因为服务不是假对象。当我尝试创建一个假对象(注释代码)时,它会给出一个错误,因为RestService是一个带有私有构造函数的单例。如何创建这个单例的假对象?

    private RestService service;

    [TestInitialize]
    public void Init()
    {
        //service = A.Fake<RestService>();
        service = RestService.Instance;
        service.CreateClient("test", "test");
    }

    [TestMethod]
    public async Task TestGetLogicalDevices()
    {
        var logicalDevices = (List<LogicalDevice>)A.CollectionOfFake<LogicalDevice>(10);
        A.CallTo(() => service.GetLogicalDevices()).Returns(Task.FromResult(logicalDevices));
        List<LogicalDevice> collectedData = await service.GetLogicalDevices();
        Assert.AreEqual(2, collectedData.Count);
    }

    public async Task<List<LogicalDevice>> GetLogicalDevices()
    {
        var response = await client.GetAsync(apiBaseUrl + "/logical-devices");
        if (response.IsSuccessStatusCode)
        {
            var json = await response.Content.ReadAsStringAsync();
            var logicalDevices = JsonConvert.DeserializeObject<List<LogicalDevice>>(json);
            var sortedList = logicalDevices.OrderBy(logicalDevice => logicalDevice.Name).ToList();
            return sortedList;
        }
        else
        {
            return null;
        }
    } 

更新 我添加了我要测试的方法代码。也许有人有更好的测试建议?

1 个答案:

答案 0 :(得分:3)

注意:我不确定我是否理解您要做的事情。你准备测试什么?在您的测试中,您将service.GetLogicalDevices()配置为返回一些东西,然后调用service.GetLogicalDevices()并断言它返回的内容(除非FakeItEasy被破坏,否则应该是您将其配置为返回的内容)。所以,你实际上没有测试服务......你正在测试模拟框架!像FakeItEasy这样的模拟框架对于模拟被测系统(SUT)的依赖性很有用,而不是SUT本身。在您的情况下,如果SUT为RestService,则需要模拟RestService的依赖关系,而不是RestService本身。例如,您可以使用您控制的HttpClient注入HttpMessageHandler(有关详情,请参阅here)。

现在,回答你的实际问题(假设它真的RestService你想假装):

  

当我运行此代码时,我在TestGetLogicalDevices()中收到错误。 CallTo()失败,因为服务不是虚假对象。

A.CallTo仅适用于假货; FakeItEasy无法控制它没有创建的对象的行为。

  

当我尝试创建一个虚假对象(注释代码)时,它会出错,因为RestService是一个带有私有构造函数的单例

RestService是一个类,FakeItEasy可以为类创建一个假,但它通过继承类来实现它,因此它需要一个可访问的构造函数。另外,请记住,只能配置虚拟方法。 GetLogicalDevices不是虚拟的,因此假的不能覆盖其行为。

伪造RestService有两个主要选项:

  • 制作构造函数protected而不是private,并将方法设为虚拟,以便可以覆盖它们
  • 创建一个代表&#34;公共合同的IRestService界面&#34; RestService类的,并伪造该接口而不是类。