Wil*_*ert 43 .net c# generics moq mocking
我有一个方法的接口如下:
public interface IRepo
{
IA<T> Reserve<T>();
}
Run Code Online (Sandbox Code Playgroud)
我想模拟包含此方法的类,而不必为它可用于的每种类型指定安装方法.理想情况下,我只是喜欢它返回一个new mock<T>.Object.
我该如何实现这一目标?
看来我的解释还不清楚.这是一个例子 - 当我指定T(这里是字符串)时,这是可能的:
[TestMethod]
public void ExampleTest()
{
var mock = new Mock<IRepo>();
mock.Setup(pa => pa.Reserve<string>()).Returns(new Mock<IA<string>>().Object);
}
Run Code Online (Sandbox Code Playgroud)
我想要实现的是这样的:
[TestMethod]
public void ExampleTest()
{
var mock = new Mock<IRepo>();
mock.Setup(pa => pa.Reserve<T>()).Returns(new Mock<IA<T>>().Object);
// of course T doesn't exist here. But I would like to specify all types
// without having to repeat the .Setup(...) line for each of them.
}
Run Code Online (Sandbox Code Playgroud)
被测对象的某些方法可能会调用三种或四种不同类型的保留.如果我必须设置所有类型,我必须为每个测试编写大量的设置代码.但是在单个测试中,我并不关心所有这些,我只需要非空的模拟对象,除了我实际测试的那个(我很乐意写一个更复杂的设置).
小智 37
在 Moq 4.13 中,他们引入了 It.IsAnyType 类型,您可以使用它来模拟泛型方法。例如
public interface IFoo
{
bool M1<T>();
bool M2<T>(T arg);
}
var mock = new Mock<IFoo>();
// matches any type argument:
mock.Setup(m => m.M1<It.IsAnyType>()).Returns(true);
// matches only type arguments that are subtypes of / implement T:
mock.Setup(m => m.M1<It.IsSubtype<T>>()).Returns(true);
// use of type matchers is allowed in the argument list:
mock.Setup(m => m.M2(It.IsAny<It.IsAnyType>())).Returns(true);
mock.Setup(m => m.M2(It.IsAny<It.IsSubtype<T>>())).Returns(true);
Run Code Online (Sandbox Code Playgroud)
Jep*_*sen 20
只需这样做:
[TestMethod]
public void ExampleTest()
{
var mock = new Mock<IRepo> { DefaultValue = DefaultValue.Mock, };
// no setups needed!
...
}
Run Code Online (Sandbox Code Playgroud)
由于你的模拟没有行为Strict,它会对你甚至没有设置的调用感到满意.在这种情况下,只返回"默认".然后
DefaultValue.Mock
Run Code Online (Sandbox Code Playgroud)
确保此"默认"是Mock<>适当类型的新类型,而不仅仅是空引用.
这里的限制是您无法控制(例如,进行特殊设置)返回的单个"子模拟".
Mik*_*oud 17
除非我误解了你的需要,否则你可以构建一个这样的方法:
private Mock<IRepo> MockObject<T>()
{
var mock = new Mock<IRepo>();
return mock.Setup(pa => pa.Reserve<T>())
.Returns(new Mock<IA<T>>().Object).Object;
}
Run Code Online (Sandbox Code Playgroud)
我发现了一种我认为更接近你想要的替代方案.无论如何它对我有用,所以这里.我们的想法是创建一个几乎纯粹抽象的中间类,并实现您的界面.不抽象的部分是Moq无法处理的部分.例如
public abstract class RepoFake : IRepo
{
public IA<T> Reserve<T>()
{
return (IA<T>)ReserveProxy(typeof(T));
}
// This will be mocked, you can call Setup with it
public abstract object ReserveProxy(Type t);
// TODO: add abstract implementations of any other interface members so they can be mocked
}
Run Code Online (Sandbox Code Playgroud)
现在你可以模拟RepoFake而不是IRepo.一切都是一样的,除了你写的设置ReserveProxy而不是Reserve.如果要基于类型执行断言,则可以处理回调,尽管Type参数to ReserveProxy是完全可选的.
| 归档时间: |
|
| 查看次数: |
38774 次 |
| 最近记录: |