Olandese
Olandese

Reputation: 188

Intercep interface method call inside another method with Moq

i have an interface:

public interface ISomeInterface
{
  public string ReturnSomeString();
}

and the interface implementation:

public class SomeInterface: ISomeInterface
{
     public string ReturnSomeString()
     {
        return "Hello";
     }
}

In another method i make a call to this interface implementation:

public class SomeClass
{

    public string DoTheCall()
    {
       ISomeInterface someInterface = new SomeInterface();
       return someInterface.ReturnSomeString();

    }
}

Now i would like with Moq that every call to ReturnSomeString will always return "Hello World"

I tried with this:

[TestClass]
public class Test
{
    [TestMethod]
    public void SomeTest()
    {
        var mock = new ISomeInterface();
        mock.Setup(x => x.ReturnSomeString()).Returns("Hello World!!!");            

        SomeClass sc = new SomeClass();

        Assert.IsTrue(sc.ReturnSomeString(), "Hello World!!!");
    }
}

But the original interface method call is always done. I don't want to use constructor injection or something like this, is there a way to tell Moq that every call to the interface or implementation (from everywhere) should return the mocked string?

Upvotes: 0

Views: 1564

Answers (3)

jvrdelafuente
jvrdelafuente

Reputation: 2002

You have to do some changes to make your code testable:

public class SomeClass
{
    private readonly ISomeInterface _someInterface;
    public SomeClass(ISomeInterface someInterface){
      _someInterface= someInterface;
    }

    public string DoTheCall()
    {
       return _someInterface.ReturnSomeString();

    }
}

And the test:

[TestClass]
public class Test
{
    [TestMethod]
    public void SomeTest()
    {
        var mock = new Mock<ISomeInterface>();
        mock.Setup(x => x.ReturnSomeString()).Returns("Hello World!!!");            

        SomeClass sc = new SomeClass(mock.Object);

        Assert.IsTrue(sc.ReturnSomeString(), "Hello World!!!");
    }
}

I think that it would make to test works.

Upvotes: 1

Alexei Levenkov
Alexei Levenkov

Reputation: 100527

No - your method explicitly instantiates class and Moq can't modify existing classes.

You options:

  • proper dependency injection via constructor, property or method argument (not what you want)
  • replace new with factory method call to allow returning different object
  • use something more heavy like Fakes

Upvotes: 3

AD.Net
AD.Net

Reputation: 13399

This would be with constructor injection.

 public class SomeClass
    {
    ISomeInterface someInterface;
        public SomeClass(ISomeInterface inter)
        {
           this.someInterface = inter;
        }
        public string DoTheCall()
        {
           return someInterface.ReturnSomeString();
        }
    }

[TestClass]
public class Test
{
    [TestMethod]
    public void SomeTest()
    {
        var mock = new ISomeInterface();
        mock.Setup(x => x.ReturnSomeString()).Returns("Hello World!!!");            

        SomeClass sc = new SomeClass(mock.Object);

        Assert.IsTrue(sc.ReturnSomeString(), "Hello World!!!");
    }
}

Otherwise you can make a property injection, which basically is like this (please note you should handle the null property)

 public class SomeClass
    {
      public ISomeInterface someInterface{get;set;}

        public string DoTheCall()
        {
           return someInterface.ReturnSomeString();
        }
    }

[TestClass]
    public class Test
    {
        [TestMethod]
        public void SomeTest()
        {
            var mock = new ISomeInterface();
            mock.Setup(x => x.ReturnSomeString()).Returns("Hello World!!!");            

            SomeClass sc = new SomeClass {someInterface = mock.Object};

            Assert.IsTrue(sc.ReturnSomeString(), "Hello World!!!");
        }
    }

Upvotes: 4

Related Questions