How to mock base class method?

14 posts, 0 answers
  1. cecilUOA
    cecilUOA avatar
    20 posts
    Member since:
    May 2007

    Posted 14 Nov 2011 Link to this post

    It's quite common that we will try to customise a Framework class but still reuse most of the logic from the base class. For example, we want to provide our own Navigation Provider inheriting from Microsoft.SharePoint.Navigation.SPNavigationProvider. And we want to override GetChildNodes class to add some addition site map node on top of the collection that base class return. So we will be calling base.GetChildNodes() from our GetChildNodes method.

    Here is a simple example. The problem is I dont know how to reference the base class method in the Mock.Arrange method?

    public class ParentClass
    {
        public virtual int Sum()
        {
            return 0;
        }
    }
    public class ChildClass : ParentClass
    {
        public override int Sum()
        {
            return 1 + base.Sum();
        }
    }
    [TestMethod]
    public void RunChildClass()
    {
        var childClass = new ChildClass();
        Mock.Arrange(() => childClass.Sum()).Returns(2); // want to override ParentClass.Sum(), not ChildClass.Sum().
        var result = childClass.Sum();
        Assert.IsTrue(result == 3); // instead I will get 2 here.
    }
  2. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 17 Nov 2011 Link to this post

    Hi Doug,

    Thanks again for making the query. The new Q3 release is out and this release let you ignore the target instance for a specific setup.

    Therefore you can rewrite the test in the following way:
    Mock.Arrange(() => new ParentClass().Sum()).Returns(2).IgnoreInstance();
     
    var childClass = new ChildClass();
     
    var result = childClass.Sum();
     
    Assert.IsTrie(result == 3);

    Here you are setting the expected return for ParentClass regardless of its instance where it is  inherited by ChildClass and ChildClass can access it via base keyword from a method.

    Hope that solves your issue.

    Kind Regads,
    Mehfuz
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft R3 2016 release webinar banner
  4. Dave
    Dave avatar
    31 posts
    Member since:
    Apr 2014

    Posted 27 Jan 2015 in reply to Ricky Link to this post

    Is there some way of doing this when the base class is abstract?
  5. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 28 Jan 2015 Link to this post

    Hello Dave,

    You can use the following syntax:
    Mock.Arrange(() => Arg.IsAny<ParentClass>().Sum()).Returns(2);
    The above implies IgnoreInstance(), so you don't have to write it explicitly.

    Regards,
    Stefan
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  6. Dave
    Dave avatar
    31 posts
    Member since:
    Apr 2014

    Posted 29 Jan 2015 in reply to Stefan Link to this post

    Hi Stefan. I tried that but it doesn't seem to work. I'm actually doing an ArrangeSet:

        Mock.ArrangeSet(()=>Arg.IsAny<ParentClass>().MyProperty = newValue).OccursOnce();

    but Arg.IsAny<ParentClass>() evaluates to null which causes a NullReferenceException.
    Can you advise?
    Dave
  7. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 30 Jan 2015 Link to this post

    Hi Dave,

    It appears that It is not possible to tell JustMock to arrange the base implementation of a virtual setter in an abstract class.

    I have logged the issue and I predict that it will be fully fixed in this year's Q2 release when the JustMock API is fully migrated to .NET 4.

    In the interim I can only suggest that you make a dummy non-abstract derived class from ParentClass and go:
    Mock.ArrangeSet(() => new DummyClass().Value = 5).IgnoreInstance().DoInstead(...)


    Regards,
    Stefan
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  8. Dave
    Dave avatar
    31 posts
    Member since:
    Apr 2014

    Posted 30 Jan 2015 in reply to Stefan Link to this post

    Nope, this just isn't working.
    Forget the abstract base class for a minute. Going back to the orginal question, and Mehfuz's answer, how would you do this if ParentClass doesn't have a default constructor?
    Dave
  9. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 04 Feb 2015 Link to this post

    Hello Dave,

    If ParentClass doesn't have a default constructor, or if ParentClass is an abstract type, then in either case you can arrange against a mock of ParentClass:
    var dummy = Mock.Create<ParentClass>();
    Mock.ArrangeSet(() => dummy.Value = Arg.AnyInt).IgnoreInstance().DoInstead(...);


    Regards,
    Stefan
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  10. Dave
    Dave avatar
    31 posts
    Member since:
    Apr 2014

    Posted 11 Feb 2015 in reply to Stefan Link to this post

    Thanks Stefan. That works a treat.
    Dave
  11. Dave
    Dave avatar
    31 posts
    Member since:
    Apr 2014

    Posted 16 Feb 2015 in reply to Stefan Link to this post

    Hi Stefan
    Unfortunately I spoke too soon. It works in principle but there seems to be a problem with it under certain circumstances. I've tracked it down as far as I can and I've found that if a partial mock is arranged on some other member of the class under test, the mock of the base class method doesn't work, in that it actually mocks out the method for the derived class as well as for the base class.
    I've set up a small demonstration project that illustrates this very clearly. I was going to attach it as a .ZIP file to this post but it seems only graphics file are allowed as attachments. If you tell me the best method to send it to you, I will.
    This would be a really useful technique and I would be most grateful if you could have a look and tell me if there is a work-around for the problem.
    FYI I am using JustMock version 2014.1.1424.1.
    Thanks
    Dave
  12. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 19 Feb 2015 Link to this post

    Hello Dave,

    You will need to use a support ticket to attach an archive file. Unfortunately, at this stage you are not assigned as a JustMock licensed user, which will prevent you from using our private support channel. You will either have to ask the license holder to add you as a licensed user and then open a new support ticket on the same matter, or simply use another way for sending us the files. For example, you can upload them to DropBox and send us the link.

    Regards,
    Kaloyan
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  13. Dave
    Dave avatar
    31 posts
    Member since:
    Apr 2014

    Posted 26 Feb 2015 in reply to Kaloyan Link to this post

    Hi Stefan/Kaloyan
    I am in the process of getting a licence from my company, but the admin takes a while. In the meantime the demonstration can be downloaded from http://www.knoware.co.uk/MockBaseClassProblem.zip
    I'd appreciate it if you could take a look.
    Dave
  14. Zdravko
    Admin
    Zdravko avatar
    657 posts

    Posted 03 Mar 2015 Link to this post

    Hello Dave,

    Thank you for sharing the project with us.
    We will review it in shortest terms possible and write you back.

    Regards,
    Zdravko
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  15. Stefan
    Admin
    Stefan avatar
    198 posts

    Posted 04 Mar 2015 Link to this post

    Hi Dave,

    Apparently this is a bug in JustMock. When dispatching mock calls, it does not distinguish between base and derived methods and applies all arrangements on every method in the inheritance chain to all methods in the chain. The first test works, because the call to the derived method does not go through JustMock, only the base call does.

    This looks like a deeply ingrained defect (or feature turned defect), so it may take a while to fix. As a token of gratitude for providing us with such a great repro, I've given you some Telerik points.

    Unfortunately, this time there is no workaround that I can think of.

    Regards,
    Stefan
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
Back to Top
DevCraft R3 2016 release webinar banner