moq只有一个类中的一个方法

我正在使用moq.dll当我模拟一个类(所有IRepository接口)时,我使用这个行代码

int state = 5; var rep = new Mock(); rep.Setup(x => x.SaveState(state)).Returns(true); IRepository repository = rep.Object; 

但在这种情况下,我模拟了存储库类中的所有函数。 然后,类库中的所有方法都被Mock dll的方法设置所取代

我想使用类库中定义的所有方法(真正的类)并且只模拟一个函数(SaveState)

我怎样才能做到这一点? 有可能吗?

您可以创建真实存储库的实例,然后使用As<>()来获取所需的接口,然后可以使用设置覆盖,如下所示:

 var mockRep = new Mock(ctorArg1, ctorArg2, ...) .As(); mockRep.Setup(x => x.SaveState(state)).Returns(true); 

然后mockRep.Object作为被测试类的存储库依赖项。 请注意,您只能以这种方式在Interface *或虚拟方法上模拟方法。

更新 :*这可能不适用于所有场景,因为.Setup仅适用于虚拟方法,而C#接口实现默认为“虚拟”并密封 。 并且使用As()将阻止部分模拟行为。

因此, RealRepository具体类似乎需要使用虚方法实现IRepository接口,以便部分模拟成功,在这种情况下, CallBase可用于连接。

  public interface IRepo { string Foo(); string Bar(); } public class RealRepo : IRepo { public RealRepo(string p1, string p2) {Console.WriteLine("CTOR : {0} {1}", p1, p2); } // ** These need to be virtual in order for the partial mock Setups public virtual string Foo() { return "RealFoo"; } public virtual string Bar() {return "RealBar"; } } public class Sut { private readonly IRepo _repo; public Sut(IRepo repo) { _repo = repo; } public void DoFooBar() { Console.WriteLine(_repo.Foo()); Console.WriteLine(_repo.Bar()); } } [TestFixture] public class SomeFixture { [Test] public void SomeTest() { var mockRepo = new Mock("1st Param", "2nd Param"); // For the partially mocked methods mockRepo.Setup(mr => mr.Foo()) .Returns("MockedFoo"); // To wireup the concrete class. mockRepo.CallBase = true; var sut = new Sut(mockRepo.Object); sut.DoFooBar(); } } 

我来到这个页面是因为我有完全相同的问题:我需要模拟一个方法,它依赖于许多外部源并可以产生三个输出中的一个,同时让其余的类完成它的工作。 不幸的是,上面提出的部分模拟方法不起作用。 我真的不知道为什么它不起作用。 但是,主要的问题是即使你把断点放在你想要的地方,你也无法在这样的模拟类中进行调试。 这不好,因为您可能真的需要调试一些东西。

所以,我使用了一个更简单的解决方案:声明所有想要模拟为虚拟的方法。 然后inheritance该类并编写单行模拟覆盖以返回您想要的内容,例如:

 public class Repository { ///  /// Let's say that SaveState can return true / false OR throw some exception. ///  public virtual bool SaveState(int state) { // Do some complicated stuff that you don't care about but want to mock. var result = false; return result; } public void DoSomething() { // Do something useful here and assign a state. var state = 0; var result = SaveState(state); // Do something useful with the result here. } } public class MockedRepositoryWithReturnFalse : Repository { public override bool SaveState(int state) => false; } public class MockedRepositoryWithReturnTrue : Repository { public override bool SaveState(int state) => true; } public class MockedRepositoryWithThrow : Repository { public override bool SaveState(int state) => throw new InvalidOperationException("Some invalid operation..."); } 

就这样。 然后,您可以在unit testing期间使用模拟的存储库,并且可以调试所需的任何内容。 您甚至可以将保护级别保留在公共级别以下,以免暴露您不想暴露的内容。