我试图模拟一个通用方法,它有一个约束T : IFoo
但是最小起订量似乎无法理解转换并给出以下错误:
类型“Moq.It.IsSubtype<SomeNamepace.IFoo>”不能用作泛型类型或方法“IMyClass.DoSomething(Action)”中的类型参数“T”。没有从“Moq.It.IsSubtype<SomeNamepace.IFoo>”到“SomeNamepace.IFoo”的隐式引用转换。
public interface IFoo
{
}
class Foo : IFoo
{
}
public interface IMyClass
{
public IDisposable DoSomething<T>(Action<T> asd) where T : IFoo;
}
public class MyTest
{
[Test]
public void SomeTest()
{
var mock = new Mock<IMyClass>();
mock.Setup(e => e.DoSomething(It.IsAny<Action<IFoo>>())).Returns(Mock.Of<IDisposable>());
// What I want but gives compiler error
// mock.Setup(e => e.DoSomething(It.IsAny<Action<It.IsSubtype<IFoo>>>())).Returns(Mock.Of<IDisposable>());
// Action<IFoo> would work, but in real code its not used like that
Action<Foo> myAction = (e) => { };
var result = mock.Object.DoSomething(myAction);
result.Dispose(); // Null reference exception
}
}
Run Code Online (Sandbox Code Playgroud)
由于It.IsSubtype<IFoo>没有实现IFoo,你不能像这样使用它。由于类型限制。
但是,您可以单独使用IFoo,这应该考虑您传入的任何值,因为它们都需要实现IFoo. 换句话说,类型约束已经为您完成了确保类型正确的繁重工作。例如,给定如下设置:
public interface IFoo
{
}
public interface IMyClass
{
string DoSomething<T>() where T : IFoo;
}
Run Code Online (Sandbox Code Playgroud)
您的测试代码将是这样的:
var mock = new Mock<IMyClass>();
mock.Setup(e => e.DoSomething<IFoo>()).Returns("cheese");
var result = mock.Object.DoSomething<IFoo>();
Assert.Equal("cheese", result); // true
Run Code Online (Sandbox Code Playgroud)
在对问题进行补充澄清后,上面的答案仍然成立,我们可以做类似的事情:
mock
.Setup(e => e.DoSomething<Foo>(It.IsAny<Action<Foo>>()))
.Returns(new MyDisposableObject());
Run Code Online (Sandbox Code Playgroud)
现在我们使用它是Foo因为我们明确地知道传入的类型,所以我们不需要再担心接口了。事实上,我们甚至可以简化代码,因为我们不再需要明确泛型类型:
mock
.Setup(e => e.DoSomething(It.IsAny<Action<Foo>>()))
.Returns(new MyDisposableObject());
Run Code Online (Sandbox Code Playgroud)
您可以创建自己的类型匹配器,它将实现IFoo以匹配通用约束:
[TypeMatcher]
public class FooTypeMatcher<T> : IFoo, ITypeMatcher
where T : IFoo
{
bool ITypeMatcher.Matches(Type typeArgument)
{
return typeof(T).IsAssignableFrom(typeArgument);
}
}
Run Code Online (Sandbox Code Playgroud)
并设置:
mock.Setup(e => e.DoSomething(It.IsAny<Action<FooTypeMatcher<IFoo>>>())) // will match any Action accepting any IFoo implementation
.Returns(Mock.Of<IDisposable>());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1282 次 |
| 最近记录: |