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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 18:04:06  来源:igfitidea点击:

How to mock a class that implements multiple interfaces

c#mockingmoq

提问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 IUserRepositoryand 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 IUserRepositoryinterface.

如果我正确理解了这个问题,您需要一个 的模拟实例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的:美孚,IFooBarClientTwo使用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>.

在为系统创建端到端测试时,我们有一个IFooBarClientOneClientTwo。的作为<>()函数允许我们使用的模拟<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());