Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

moq only one method in a class

Tags:

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?

like image 529
user3401335 Avatar asked Jul 07 '14 09:07

user3401335


People also ask

How do you mock a method in the same class?

We can mock runInGround(String location) method inside the PersonTest class as shown below. Instead of using mock(class) here we need to use Mockito. spy() to mock the same class we are testing. Then we can mock the method we want as follows.

How do you mock a method in Moq?

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it. Finally, we call the method we are testing and assert the results.

Can you mock a class with Moq?

You can use Moq to create mock objects that simulate or mimic a real object. Moq can be used to mock both classes and interfaces. However, there are a few limitations you should be aware of. The classes to be mocked can't be static or sealed, and the method being mocked should be marked as virtual.

How do you mock another method in the same class which is being tested C#?

You can either mock the external calls that happen within the getTyreSpecification method or you can pull that method out into its own class, wrapped in an interface, and inject the interface into your Selecter class. That would allow you to mock it.


2 Answers

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();       }    } 
like image 51
StuartLC Avatar answered Sep 20 '22 21:09

StuartLC


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.

like image 38
Konstantin Konstantinov Avatar answered Sep 21 '22 21:09

Konstantin Konstantinov