return IEnumerable 类型的模拟方法
Mocking methods that return IEnumerable types
我 运行 在一个更大的背景下解决这个问题,但是当浓缩到最低限度时,剩下的问题是为什么 Moq 不是 return 指定的类型 在接口 中用于模拟方法? IEnumerable 和 List 作为空数组返回,
当我使用 return 值专门调用 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 似乎 return 一个空数组,即使我专门用一个空列表(复杂类型)设置它,但我稍后会问这个问题。
更新并重新表述我的问题
我没有考虑到数组是一个 IEnumerable,我的接口有 IEnumerable,因此 Moq returns 没有错。当我将界面更改为列表时,Mock return 是一个列表。
我还没准备好更改代码中的 return 类型。我可以自定义调整我的断言来处理任何一种类型,但是:
我正在为一个 API 编写单元测试,其中包含许多执行类似操作的端点。我正在尝试在基础 class 中生成我的断言代码,但我并不总是知道我是在处理数组还是列表。
我该如何解决这个问题?我是否应该完全避免将 IEnumerable 用作 return 类型?
这在评论中得到了回答,但我讨厌这个问题在没有正式答案的情况下四处飘荡,所以请允许我回顾一下:
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 重要的是接口中的类型,而不是实现。因此,如果没有通过设置给出特定的 return 类型,则您不能对 Mock return 的类型做出假设。在我的例子中,默认值是一个数组。这使得试图以列表形式访问结果的代码无效(在我这里的示例中不是)。
按照@Guru Stron 的建议,将其转换为 IEnumerable<T>
并使用 ToList()
,解决了类型歧义并使其适用于任何一种情况 - 明确 return 的设置是一个 List<T>
或 Mock 默认值 return 是一个空的 <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!
现在你可能会说:这个post中有很多词(以及下载它们需要带宽)得出一个相当琐碎的结论。我要否决这个问题和这个答案,但让我问你这个:你知道 Moq returns 是 IEnumerables 的数组类型,如果没有给出其他类型的设置吗?
我 运行 在一个更大的背景下解决这个问题,但是当浓缩到最低限度时,剩下的问题是为什么 Moq 不是 return 指定的类型 在接口 中用于模拟方法? IEnumerable 和 List 作为空数组返回,
当我使用 return 值专门调用 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 似乎 return 一个空数组,即使我专门用一个空列表(复杂类型)设置它,但我稍后会问这个问题。
更新并重新表述我的问题
我没有考虑到数组是一个 IEnumerable,我的接口有 IEnumerable,因此 Moq returns 没有错。当我将界面更改为列表时,Mock return 是一个列表。
我还没准备好更改代码中的 return 类型。我可以自定义调整我的断言来处理任何一种类型,但是:
我正在为一个 API 编写单元测试,其中包含许多执行类似操作的端点。我正在尝试在基础 class 中生成我的断言代码,但我并不总是知道我是在处理数组还是列表。
我该如何解决这个问题?我是否应该完全避免将 IEnumerable 用作 return 类型?
这在评论中得到了回答,但我讨厌这个问题在没有正式答案的情况下四处飘荡,所以请允许我回顾一下:
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 重要的是接口中的类型,而不是实现。因此,如果没有通过设置给出特定的 return 类型,则您不能对 Mock return 的类型做出假设。在我的例子中,默认值是一个数组。这使得试图以列表形式访问结果的代码无效(在我这里的示例中不是)。
按照@Guru Stron 的建议,将其转换为 IEnumerable<T>
并使用 ToList()
,解决了类型歧义并使其适用于任何一种情况 - 明确 return 的设置是一个 List<T>
或 Mock 默认值 return 是一个空的 <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!
现在你可能会说:这个post中有很多词(以及下载它们需要带宽)得出一个相当琐碎的结论。我要否决这个问题和这个答案,但让我问你这个:你知道 Moq returns 是 IEnumerables 的数组类型,如果没有给出其他类型的设置吗?