如何模拟实现多个接口的类

时间:2013-04-04 20:01:48

标签: c# mocking moq

如何模拟以下类:

UserRepository : GenericRepository<User>, IUserRepository


public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class

我正在使用Moq,我很困惑如何正确处理多个接口。

4 个答案:

答案 0 :(得分:63)

查看https://github.com/Moq/moq4/wiki/Quickstart

高级功能

// 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());

答案 1 :(得分:23)

Moq内置了一种机制来处理多个接口。

假设我们有一个界面 IFoo ,并且实现了相同的 Foo 。我们还有使用IFoo的 ClientOne

然后我们有一个接口 IFooBar:IFoo ,一个实现 FooBar:Foo,IFooBar 和一个使用IFooBar的 ClientTwo

在为系统创建端到端测试时,我们有 IFooBar ClientOne ClientTwo As&lt;&gt;()功能允许我们将 Mock&lt; IFooBar&gt; 用作 Mock&lt; IFoo&gt;

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);

}

答案 2 :(得分:3)

你不要模拟,你要模拟接口。在你的情况下,你可以有两个模拟 - 一个模拟IUserRepository,另一个模拟IGenericRepository<User>。它们不一定是同一个对象 - 如果它们必须是同一个对象,那么它可能是一个设计缺陷。

答案 3 :(得分:3)

如果我正确理解了这个问题,你想要一个UserRepository的模拟实例,并且为了测试的目的,设置从IGenericRepository<TEntity>接口和{{1}的方法调用接口。

您可以使用单个模拟实例实现多个接口,如下所示:

IUserRepository

然而,正如D Stanley指出的那样,需要这样做可能表明你的设计存在缺陷。