Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I mock a private field?

Tags:

I'm really new to mocks and am trying to replace a private field with a mock object. Currently the instance of the private field is created in the constructor. My code looks like...

public class Cache {
    private ISnapshot _lastest_snapshot;

    public ISnapshot LatestSnapshot {
        get { return this._lastest_snapshot; }
        private set { this._latest_snapshot = value; }
    }

    public Cache() {
        this.LatestSnapshot = new Snapshot();
    }

    public void Freeze(IUpdates Updates) {
        ISnapshot _next = this.LastestSnapshot.CreateNext();
        _next.FreezeFrom(Updates);
        this.LastestSnapshot = _next;
    }

}

What I'm trying to do is create a unit test that asserts ISnapshot.FreezeFrom(IUpdates) is called from within Cache.Freeze(IUpdates). I'm guessing I should replace the private field _latest_snapshot with a mock object (maybe wrong assumption?). How would I go about that while still retaining a parameterless constructor and not resorting to making LatestSnapshot's set public?

If I'm totally going about writing the test the wrong way then please do point out as well.

The actual implementation of ISnapshot.FreezeFrom itself calls a heirarchy of other methods with a deep object graph so I'm not too keen on asserting the object graph.

Thanks in advance.

like image 998
Fung Avatar asked Feb 25 '09 05:02

Fung


People also ask

Can you mock a private function?

For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.


1 Answers

I'm almost citing techniques from "Working Effectively with Legacy Code":

  1. Sub-class your class in a unit test and supersede your private variable with a mock object in it (by adding a public setter or in the constructor). You probably have to make the variable protected.
  2. Make a protected getter for this private variable, and override it in testing subclass to return a mock object instead of the actual private variable.
  3. Create a protected factory method for creating ISnapshot object, and override it in testing subclass to return an instance of a mock object instead of the real one. This way the constructor will get the right value from the start.
  4. Parametrize constructor to take an instance of ISnapshot.
like image 153
Alex B Avatar answered Nov 16 '22 16:11

Alex B