C# 如何模拟实现多个接口的类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15820642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to mock a class that implements multiple interfaces
提问by loyalflow
How to mock the following class:
如何模拟以下类:
UserRepository : GenericRepository<User>, IUserRepository
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
I am using Moq, and I am confused how to handle multiple interfaces correctly.
我正在使用 Moq,我对如何正确处理多个接口感到困惑。
回答by D Stanley
You don't mock classes, you mock interfaces. In your case you could have two mocks - one that mocks IUserRepository
and one that mocks IGenericRepository<User>
. They shouldn't necessarily be the same object - if they DO have to be the same object, then it may be a design flaw.
你不模拟类,你模拟接口。在您的情况下,您可以有两个模拟 - 一个模拟IUserRepository
和一个模拟IGenericRepository<User>
。它们不一定是同一个对象——如果它们必须是同一个对象,那么它可能是一个设计缺陷。
回答by Alex Peck
If I understand the question correctly, you want have a single mock instance of UserRepository
, and for the purposes of a test, setup calls to methods from both the IGenericRepository<TEntity>
interface and the IUserRepository
interface.
如果我正确理解了这个问题,您需要一个 的模拟实例UserRepository
,并且为了测试的目的,从IGenericRepository<TEntity>
接口和IUserRepository
接口设置对方法的调用。
You can implement multiple interfaces with a single mock instance like this:
您可以使用单个模拟实例实现多个接口,如下所示:
var genericRepositoryMock = new Mock<IGenericRepository<User>>();
genericRepositoryMock.Setup(m => m.CallGenericRepositoryMethod()).Returns(false);
var userRepositoryMock = genericRepositoryMock.As<IUserRepository>();
userRepositoryMock.Setup(m => m.CallUserRepositoryMethod()).Returns(true);
However, as D Stanley pointed out, the need to do this is probably an indication that there is a flaw in your design.
但是,正如 D Stanley 指出的那样,需要这样做可能表明您的设计存在缺陷。
回答by AlanT
There is a mechanism built into Moq for dealing with multiple interfaces.
Moq 中内置了一种机制来处理多个接口。
Say we have an interface IFooand an implementation of the same Foo. We also have ClientOnethat uses IFoo.
假设我们有一个接口IFoo和一个相同的Foo的实现。我们还有使用 IFoo 的ClientOne。
We then have an interface IFooBar : IFoo, an implementation FooBar : Foo, IFooBarand a ClientTwothat uses IFooBar.
然后,我们有一个接口IFooBar:IFoo的,实现FooBar的:美孚,IFooBar和ClientTwo使用IFooBar。
When creating an end-to-end test for the system we have an IFooBar, ClientOneand ClientTwo. The As<>()function allows us to use the Mock<IFooBar>as a Mock<IFoo>.
在为系统创建端到端测试时,我们有一个IFooBar、ClientOne和ClientTwo。的作为<>()函数允许我们使用的模拟<IFooBar>作为模拟<IFoo的>。
public interface IFoo {
int Id { get; }
}
public class Foo : IFoo {
public int Id {
get { return 1; }
}
}
public interface IFooBar : IFoo {
string Name { get; }
}
public class FooBar : Foo, IFooBar {
public string Name {
get { return "AName"; }
}
}
public class ClientOne {
private readonly IFoo foo;
public ClientOne(IFoo foo) {
this.foo = foo;
}
public string Details {
get { return string.Format("Foo : {0}", foo.Id); }
}
}
public class ClientTwo {
private readonly IFooBar fooBar;
public ClientTwo(IFooBar fooBar) {
this.fooBar = fooBar;
}
public string Details {
get { return string.Format("Foo : {0}, Bar : {1}", fooBar.Id, fooBar.Name); }
}
}
[TestMethod]
public void TestUsingBothClients() {
var fooBarMock = new Mock<IFooBar>();
var fooMock = fooBarMock.As<IFoo>();
fooBarMock.SetupGet(mk => mk.Id).Returns(1);
fooBarMock.SetupGet(mk => mk.Name).Returns("AName");
var clientOne = new ClientOne(fooMock.Object);
var clientTwo = new ClientTwo(fooBarMock.Object);
Assert.AreEqual("Foo : 1", clientOne.Details);
Assert.AreEqual("Foo : 1, Bar : AName", clientTwo.Details);
}
回答by ShloEmi
Take a look at https://github.com/Moq/moq4/wiki/Quickstart
看看https://github.com/Moq/moq4/wiki/Quickstart
Advanced Features
高级功能
// implementing multiple interfaces in mock
var foo = new Mock<IFoo>();
var disposableFoo = foo.As<IDisposable>();
// now IFoo mock also implements IDisposable :)
disposableFoo.Setup(df => df.Dispose());