繁体   English   中英

返回 IEnumerable 类型的 Mocking 方法

[英]Mocking methods that return IEnumerable types

我在更大的上下文中遇到了这个问题,但是当浓缩到最低限度时,剩下的问题是为什么 Moq 不返回接口中为模拟方法指定的类型? IEnumerable 和 List 返回为空 arrays,当我专门用返回值调用 Setup 时,它至少在下面的示例中会发生变化。

    public interface ITestTarget    {
        public IEnumerable<int> getSomeData();
    }

    public class TestTarget : ITestTarget    {
        public List<int> getSomeData() {return new List<int>() { 1 };  }
    }

    public class MockTest     {
        [Fact]
        public void TestMe()
        {
            var testMock = new Mock<ITestTarget>();
            var someResult = testMock.Object.getSomeData();

            Assert.IsType<Int32[]>(someResult);    // Why does this pass? someResult is an Integer array!

            testMock.Setup(m => m.getSomeData()).Returns(new List<int> { });   // forcing it to a list

            someResult = testMock.Object.getSomeData();

            Assert.IsType<List<int>>(someResult);    // Now it is a list
        }
    }

我真正的问题是 Moq 似乎返回一个空数组,即使我专门用一个空列表(复杂类型)设置它,但我稍后会问这个问题。

更新并重新表述我的问题

我没有考虑到数组是 IEnumerable 的事实,我的接口具有 IEnumerable,因此 Moq 返回的内容没有错。 当我将接口更改为 List 时,Mock 返回一个 List。

我还没准备好更改代码中的返回类型。 我可以自定义调整我的断言来处理任何一种类型,但是:

我正在为 API 编写单元测试,其中有许多做类似事情的端点。 我试图在基本 class 中泛化我的断言代码,但我并不总是知道我是在处理数组还是列表。

我该如何解决这个问题? 我应该完全避免使用 IEnumerable 作为返回类型吗?

这在评论中得到了回答,但我不想让这个问题在没有正式答案的情况下四处流传,所以请允许我回顾一下:

public interface ITestTarget    {
    public ⚠️IEnumerable<int>⚠️ getSomeData();
}

public class TestTarget : ITestTarget     {
    public ⚠️List<int>⚠️ getSomeData() {return new List<int>() { 1 };  }
}

var testMock = new Mock<ITestTarget>();
var someResult = testMock.Object.getSomeData();

// someResult can be any type that implements IEnumerable. We cannot make
// any further assumptions. My code assumed a List.

对 Mock 来说重要的是接口中的类型,而不是实现。 因此,如果没有通过设置给出特定的返回类型,则您无法对 Mock 返回的类型做出假设。 就我而言,默认值是一个数组。 这使得试图以列表形式访问结果的代码无效(不在我的示例中)。

将其转换为IEnumerable<T>并使用ToList() ,正如@Guru Stron 所建议的那样,解决了类型歧义并使其适用于任何一种情况 - 显式返回List<T>的设置或返回的 Mock 默认值空<T>[]

这实际上与最小起订量或单元测试无关,而是与正确使用类型和接口有关。 现在我明白了,我可以用不同的方式来说明我的误解:

    int[] a = {1,2,3};

    List<int> d = (List<int>)a;     // can't do that!
    
    List<int> c = (a as IEnumerable<int>).ToList();     // do this!

现在你可能会说:这篇文章中有很多词(以及下载它们所需的带宽)来得出一个相当微不足道的结论。 我将否决这个问题和这个答案,但让我问你这个问题:你知道吗,如果没有为其他类型提供设置,Moq 会为 IEnumerables 返回一个数组类型?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM