返回 IEnumerable 类型的模拟方法

如何解决返回 IEnumerable 类型的模拟方法

我在更大的上下文中遇到了这个问题,但是当压缩到最低限度时,剩下的问题是为什么 Moq 不返回接口 中指定的类型 用于模拟方法? IEnumerable 和 List 作为空数组返回, 当我使用返回值专门调用 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 似乎返回一个空数组,即使我用空 List(复杂类型)专门设置它,但我稍后会问这个问题。

更新并重新表述我的问题

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

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

我正在为一个 API 编写单元测试,该 API 具有许多执行类似操作的端点。我试图在基类中泛化我的断言代码,但我并不总是知道我是在处理数组还是列表。

我该如何解决这个问题?我应该完全避免使用 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 返回的类型做出假设。就我而言,默认值是一个数组。这使得尝试将结果作为列表访问的代码无效(不在我这里的示例中)。

按照@Guru Stron 的建议,将其强制转换为 IEnumerable<T> 并使用 ToList() 可解决类型歧义并使其适用于任何一种情况 - 一个明确返回 List<T> 的设置或返回空 <T>[] 的 Mock 默认值。

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

    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 返回一个数组类型吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?