Mocking base class with ctor

8 posts, 0 answers
  1. Anthony
    Anthony avatar
    41 posts
    Member since:
    Apr 2012

    Posted 07 Aug 2012 Link to this post

    I have a simple scenario.  I'm trying to mock a base class that creates a Guid and sets that to a property in the ctor.  I thought I could do that with the following code; however, the mocked object is not calling the ctor.  The result is that my property is Guid.Empty and my unit test fails.

    What do I need to do to make this work?  In the meantime, I've just created a concrete class to make my test pass.  However, I'd rather get away from that and use JustMock.

    var source = Mock.Create<FooBase>(Constructor.Mocked);

  2. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 10 Aug 2012 Link to this post

    Hi Anthony,

    Thanks again for contacting us.  The mocked object should not be calling ctor since you have used Constructor.Mocked. 

    Therefore, your syntax should be something like:


    var source = Mock.Create<FooBase>(#your arguments#);

     

    Kind Regards
    Ricky
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. DevCraft R3 2016 release webinar banner
  4. Anthony
    Anthony avatar
    41 posts
    Member since:
    Apr 2012

    Posted 11 Aug 2012 Link to this post

    Ricky,

    The problem is that my constructor doesn't have parameters.  But knowing that I had the logic backwards led me to this.  It works, but I imagine it wouldn't be a good option if I was doing a more complex mock.

    I'd appreciate if you'd let me know if there is a better way.

    var source = Mock.Create<EventBase>(Constructor.NotMocked, Behavior.CallOriginal);
  5. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 14 Aug 2012 Link to this post

    Hi Anthony,

    Thanks again for contacting us. Generally, if you don't mention Constructor.Mocked then by default it will always call the original constructor. This is more or less similar to all mocking tools and also by default the mock will act as a stub therefore unless you specify Behavior.CallOriginal it should not call the original methods.

    In case you want to pass the GUID to the mock object constructor, you can write this:

    var foo = Mock.Create<Foo>(() => new Foo(Guid.NewGuid()));


    Hope this answers your question.

    P.S. On August 23rd, we are doing a JustMock webinar with Chris Eargle (Just Evangelist and C# MVP), please feel free to join and share your valuable insights that might help us align the product better.

    Here goes the link to signup:
    https://www1.gotomeeting.com/register/210978177


    Kind Regards
    Mehfuz
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  6. Anthony
    Anthony avatar
    41 posts
    Member since:
    Apr 2012

    Posted 14 Aug 2012 Link to this post

    Thank you for the reply, but your suggestions don't apply to my scenario (see original).  Here's a summary:
    • I'm mocking a base class, so there's no ctor to call directly
    • My ctor doesn't have parameters, the Guid is created in the body of the ctor
  7. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 17 Aug 2012 Link to this post

    Hi Anthony,

    Thanks again for your reply. 

    However, even you are mocking a base class that has a default constructor or constructor with no parameter unless you are specifying Constructor.Mocked it should be called.  Also, I would request you to send us a sample of the scenario that does not work for you so that we can investigate further and provide you with a better solution or alternative.

    In addition, we will also check if mocking an abstract class raises the issue where the default constructor is never been called if mocked.


    Kind Regards
    Ricky
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  8. Anthony
    Anthony avatar
    41 posts
    Member since:
    Apr 2012

    Posted 20 Aug 2012 Link to this post

    I'll run through the code for the sake of having it all documented in case someone else runs into the same problem.  I can send a test project if you want, but I cannot attach it to this post.

    Define my base class with the side effect in the ctor.
    public abstract class BaseObject {
        protected BaseObject() {
            Id = Guid.NewGuid();
        }
     
        public Guid Id { get; private set; }
    }

    Now, define the test to ensure the Id property is set when a concrete object is created.  I create a test project, a test class, and then define the test.  This is where I use JustMock.
    [TestMethod]
    public void IdAssignedInCtor() {
        var source = Mock.Create<BaseObject>();
        var notExpected = Guid.Empty;
     
        var actual = source.Id;     // ctor not called if this is Guid.Empty
        Assert.AreNotEqual(notExpected, actual);
    }

    This fails when the test runs.  The Id property is not set, because the ctor is not called.  But, if I use a different overload it works.
    [TestMethod]
    public void IdAssignedInCtorAlt() {
        var source = Mock.Create<BaseObject>(Constructor.NotMocked, Behavior.CallOriginal);
        var notExpected = Guid.Empty;
     
        var actual = source.Id;
        Assert.AreNotEqual(notExpected, actual);
    }


  9. Ricky
    Admin
    Ricky avatar
    467 posts

    Posted 23 Aug 2012 Link to this post

    Hi Anthony,

    Thanks again for providing the sample. 

    However this will work if you just apply Behavior.CallOriginal on the Id property. By default when you create a mock, it acts as a stub therefore it won’t invoke the original getter method of the property and will return Guid.Empty, but it as expected calls the constructor.



    [Test]
    public void IdAssignedInCtor()
    {
        var source = Mock.Create<BaseObject>();
        var notExpected = Guid.Empty;
     
        Mock.Arrange(() => source.Id).CallOriginal();
     
        var actual = source.Id;   // this will pass
        Assert.AreNotEqual(notExpected, actual);
    }


    Hope this answers your question.
     
    Kind Regards
    Ricky
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

Back to Top
DevCraft R3 2016 release webinar banner