3

Here's my code:

public class Bar { }

public class Foo { public string Name { get; set; } public Bar TheBar { get; set; } }

public class Dependency
{
    public Foo DoSomething(Expression<Func<Foo, bool>> exp1) { return new Foo(); }
}

public class Base
{
    public Dependency Dependency { get; set; }
    public virtual Foo MethodA(Expression<Func<Foo, bool>> exp1,
                               params Expression<Func<Foo, object>>[] exp2)
    {
        return Dependency.DoSomething(exp1);
    }
}

public class Derived : Base
{
    public Foo DerviedMethod(string str)
    {
        return base.MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);
    }
}

And my Unit Test code:

var mock = new Mock<Derived> { CallBase = true }; // Same result with false
mock
   .Setup(m => m.MethodA(
      It.IsAny<Expression<Func<Foo, bool>>>(),
      It.IsAny<Expression<Func<Foo, object>>>()
      ))
   .Returns(new Foo());

// Act
var result = mock.Object.DerviedMethod("test");

// Assert
Assert.IsNotNull(result);

But it still calls the original method and not the mocked one. Both classes exist in same assembly.

I have searched about it and almost all people got it right with CallBase = true or false.

Any ideas what is wrong with above code?

forsvarir
  • 10,749
  • 6
  • 46
  • 77
kuzzanagi
  • 55
  • 1
  • 1
  • 7
  • Shouldn't your Derived method be marked as `virtual`? Otherwise I think you can't mock concrete classes properly. Not sure tho. – Pierre-Luc Pineault Jul 03 '15 at 05:07
  • I have marked it as `virtual` but now it returns `null` and not the bar instance – kuzzanagi Jul 03 '15 at 05:12
  • The problem is probably coming from your `Setup` then. You can try to find what's the problem by removing more fluff, like the various `Expression`s parameters and generics to get to the core. Wasn't able to get your example to compile on my side. – Pierre-Luc Pineault Jul 03 '15 at 05:28
  • Thanks. I have updated to code to make it compile-able. I am trying to slim the code on my side as well. – kuzzanagi Jul 03 '15 at 05:41
  • @Pierre-LucPineault I've simplified the example but still having no success :S – kuzzanagi Jul 03 '15 at 06:10
  • 1
    Me neither, looks like it might be something Moq can't do. Similar answers/comments like [this one](http://stackoverflow.com/a/28232452/2316200) seems to draw the same conclusions. Changing your architecture from inheritance to composition (So that Derive have an instance of Base, instead of inheriting from it) could probably solve your problems though. That way you can mock the Base class directly and pass your mock to your Derived class. – Pierre-Luc Pineault Jul 03 '15 at 06:11
  • 1
    You haven't included what `DoTest` does, however you can't mock the code as it's currently written. Your calling the method you're trying to mock out, via a `base.` specifier, which tells the implementation to run a specific version of the function. Any virtual declaration is ignored, so it can't be intercepted by Moq. It's basically the same issue I discussed in this answer (the limitations on Moq and NSubstitute are the same for this) http://stackoverflow.com/a/31062287/592182 – forsvarir Jul 03 '15 at 06:26
  • Thanks, it helps. In my scenario (the original example), I had dependency extracted so I will go for mocking the dependency instead of mocking base class' method. – kuzzanagi Jul 03 '15 at 06:29

1 Answers1

0

As has been suggested by @Pierre-Luc in the comments, extracting the base class and injecting it as a dependency is probably the better approach (I always think mocking the class you're actually trying to test feels wrong).

That said, for you to be able to mock a call of a class, it needs to be made via the VTable. Essentially, the mocking framework creates a new implementation of the virtual method. When you call it normally, this version of the method is run and can then intercept calls. The problematic line is this one:

return base.MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);

Because you're explicitly calling MethodA, via the base keyword, it tells the compiler to call a particular version of the method. It's always going to call the base implementation. This means that the mock can't intercept the call.

Changing the method to:

public Foo DerviedMethod(string str) {
    return MethodA(e1 => e1.Name.Equals(str), e2 => e2.TheBar);
}

Allows the MethodA method to be mocked. Whether or not this is the right thing from a design perspective is up to you.

forsvarir
  • 10,749
  • 6
  • 46
  • 77