28

I'm using moq.dll When I mock a class(all the IRepository interface) i use this line code

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

but in this case i mock all the function in repository class. Then all the methods in class repository are substituted with the methods setup of Mock dll

I want use all the methods defined in class repository(the real class) and mock only one function(SaveState)

How can I do this? Is possible?

Liath
  • 9,913
  • 9
  • 51
  • 81
user3401335
  • 2,335
  • 2
  • 19
  • 32
  • You do know you can call rep.Setup multiple times right? – Liath Jul 07 '14 at 09:49
  • 1
    Is SaveState `virtual` ? – DaveShaw Jul 07 '14 at 09:52
  • 1
    SaveState is not virtual. Liath why set rep multiple times? i want use setup only for this method. the other methods must work as the real world – user3401335 Jul 07 '14 at 09:56
  • If you aren't controlling what your repository responds to every call then its not really unit testing. To do what you want you could make your rep a proxy to a real `IRepository` and mock all the methods to pass through their requests to the real `IRepository`. This seems like a very code smell thing to do though to me. – Chris Jul 07 '14 at 10:07
  • 3
    The `Mock.CallBase` property controls this. However, having to do this is usually a code smell – Ben Aaronson Jul 07 '14 at 10:09

2 Answers2

41

You can create an instance of the real repository, then use the As<>() to obtain the desired interface, which you can then override with the setup, like this:

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

Then mockRep.Object as the repository dependency to the class under test. Note that you will only be able to Mock methods on the Interface*, or virtual methods, in this way.

Update : *This might not work in all scenarios, since .Setup will only work on virtual methods, and C# interface implementations are "virtual" and sealed by default. And using As() will prevent the partial mock behaviour.

So it appears that the RealRepository concrete class will need to implement the IRepository interface with virtual methods in order for the partial mock to succeed, in which case CallBase can be used for the wire-up.

   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<RealRepo>("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();
      }
   }
Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • 1
    All worked great, the "sut" wording for the base wire-up class has some meaning on this ? – love2code Nov 13 '19 at 17:39
  • 1
    Yeah, `sut` is a fairly widespread term for [system under test](https://en.wikipedia.org/wiki/System_under_test) which in Unit Testing terms would mean the specific class that you're testing (by providing mocked dependencies to it). – StuartLC Nov 13 '19 at 17:45
  • 1
    Initially, the answer didn't work out for me. However, on a second look, I noticed that `Mock.CallBase` needs to be `true` to make the answer work, just as @Ben Aaronson mentioned in his comment as well. – Randy Wink May 20 '21 at 09:00
2

I came to this page because I had exactly the same problem: I needed to mock a single method, which was relying on many external sources and could produce one of three outputs, while letting the rest of the class do its work. Unfortunately the partial mock approach proposed above did not work. I really don't know why it did not work. However, the main problem is that you can't debug inside such mocked class even if you put break points where you want. This is not good because you might really need to debug something.

So, I used a much simpler solution: Declare all methods that you want to mock as virtual. Then inherit from that class and write one-liner mock overrides to return what you want, for example:

public class Repository
{
    /// <summary>
    /// Let's say that SaveState can return true / false OR throw some exception.
    /// </summary>
    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...");
}

That's all. You can then use your mocked repos during unit tests AND you can debug anything you need. You can even leave the protection level below public so that not to expose what you don't want to expose.