Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I provide a methods implementation using Moq?

I have an interface with a few methods. I have a default implementation of this interface. For the purpose of integration tests I would like to create a mock implementation that returns my custom value if one of these methods is called, and falls back to the default implementation otherwise. Is it possible with Moq, or should I create a simple stub myself?

EXAMPLE

IInterface default = new DefaultImplementation();
var mock = new Mock<IInterface>();
mock.Setup(i => i.Method(It.IsAny<>())).Calls(p => p==0 ? return 5 : default.Method(p););

TheMethodITest(mock.Object()); //if it calls the object with 0 then it should get 5, otherwise it should call the default object
like image 933
Grzenio Avatar asked Jun 11 '14 14:06

Grzenio


People also ask

How does Moq framework work?

Moq, how it works The idea is to create a concrete implementation of an interface and control how certain methods on that interface responds when called. This will allow us to essentially test all of the paths through code.

How do you mock a method in Nunit?

The three key steps to using mock objects for testing are: Use an interface to describe the object. Implement the interface for production code. Implement the interface in a mock object for testing.

How do you set a mock object property?

You can set the mock object property to the value returned by the mock object method. To achieve this, specify separate behaviors for the method and the property. You can specify one behavior at a time. For more information about mock object behavior, see Specify Mock Object Behavior.

What is callback in Moq?

Callbacks. A powerful capability of Moq is to attach custom code to configured methods and properties' getters and setters. This capability is often referred to as Callbacks.


2 Answers

You can do this, by setting the Mock to the concrete class and using As() to retrieve the underlying IInterface, on which the setup is done. You can then hard cast mock.Object to invoke the underlying concrete object:

  [Test]
  public void SomeTest()
  {
     var mock = new Mock<DefaultImplementation>().As<IInterface>();
     mock.Setup(i => i.Method(It.IsAny<int>()))
         .Returns<int>(p => p == 0 
                                 ? 5 
                                 : ((DefaultImplementation)mock.Object).Method(p));

     TheMethodITest(mock.Object);
  }

Here's the rest of the setup I tested with, FWIW:

public interface IInterface
{
   int Method(int p);
}
public class DefaultImplementation : IInterface
{
   public int Method(int p)
   {
      return 6;
   }
}
[TestFixture]
public class SomeFixture
{
   public static void TheMethodITest(IInterface dep)
   {
      for (var i = 0; i < 10; i++)
      {
         Debug.WriteLine("{0}:{1}",i, dep.Method(i));
      }
   }
} 
like image 77
StuartLC Avatar answered Nov 12 '22 02:11

StuartLC


I'm not sure what is the condition for providing default or your specific value. However, it sounds like you want to set up a mock instance with Delegator.

public void MoqCanBeSetupWithDelegator()
{
    var mock = new Mock<IInterface>();
    Func<string, int> valueFunction = i => i == "true" ? 1 : default(int);
    mock.Setup(x => x.Method(It.IsAny<string>())).Returns(valueFunction);

    Assert.Equal(1, mock.Object.Method("true"));
    Assert.Equal(0, mock.Object.Method("anonymous"));
}

public interface IInterface
{
    int Method(string arg);
}

As you can see, the Returns method is overloaded to accept a returned value(int) or delegator representing the mocked method signature. You can use Func<string, int> to replace the actual implementation - int Method(string arg).

like image 25
Jin-Wook Chung Avatar answered Nov 12 '22 02:11

Jin-Wook Chung