Mocking a private field

12,044

You can't mock anything that's private, static, or essentially - non overridable (this comes as a free mocking libraries limitation).

What you usually do in such situations (when it appears that private member has to be tested), is extracting your private member to a separate class and inject it to tested class as a dependency.

In your case, you actually need to extract code that creates _sMediaPlanObjective, which is this line:

this._sMediaPlanObjective =
    (MPWrapper.Instance).getMediaPlanObjective(sMediaPlanId);

Object that provides getMediaPlanObjective method should be injected to your tested class. If you do so, you can simply mock that object and tell it to return mocked version of _sMediaPlanObjective.

Share:
12,044
Samuel Heaney
Author by

Samuel Heaney

Updated on June 04, 2022

Comments

  • Samuel Heaney
    Samuel Heaney almost 2 years

    I know a similar question has been asked but I have not found a clear solution. I'm trying to mock a private field from a large class. The private field gets instantiated in some earlier method and I'm trying to unit test a latter method which references the field.

    So I have an earlier method in my class:

    public bool validateAll(ref DataEntry[] oEntries, string sMediaPlanId, ITemplateGenerator oTempGen)
    {
      ...
      // private field that I am trying to mock
      this._sMediaPlanObjective = (MPWrapper.Instance).getMediaPlanObjective(sMediaPlanId);
      ...
    }
    

    And I'm trying to Unit test a method that references the private field:

    public bool validateFlightObjective(ref MPDataEntry oEntry)
    {
      ...
      string entryFlightObjective = oEntry.getFlightObjective();
      string mediaPlanObjective = this._sMediaPlanObjective;
    
      if (entryFlightObjective != mediaPlanObjective)
      {
        return false;
      }
      ...
    
      return true;      
    }
    

    Given that I have a large class and this is just one method I want to test, is there a possible way to just mock this private field? Am I missing something basic or should I consider some other approach?

  • Samuel Heaney
    Samuel Heaney almost 12 years
    I don't want to test the private field itself. Wouldn't calling the method that initializes the private field violate the isolation of behavior in the unit test? Also, calling it would mean calling several other methods that need to be called sequentially and access a DB.
  • Samuel Heaney
    Samuel Heaney almost 12 years
    Would this mean having to call validateAll() to set up the mocked version of the private member so that I can test validateFlightObjective()? Or would it be better practice to make some public/protected accessor to setup the private member.
  • k.m
    k.m almost 12 years
    @SamuelHeaney: most likely so. If assignment to private field is done only in validateAll method (and cannot be done elsewhere, say in constructor once dependency is injected), then it needs to be called to set the mock. Adding extra accessor solely for the purpose of unit testing should be last resort.