Re: [mockito] How to mock a class with private static logger instance ?

6,214 views
Skip to first unread message

Eric Lefevre-Ardant

unread,
Jan 30, 2013, 10:33:45 AM1/30/13
to moc...@googlegroups.com
Well, of course, you can always mock/spy a class regardless of whether it contains private or static things.

Maybe your question is on whether you can mock a private variable ? Well, the answer is simple : Mockito does not support mocking variables, static or not.
It seems to me that you can get what you want simply by making the variable configurable via a constructor. In fact, I often have a constructor that takes a mocked logger specifically for checking that the logger is being called correctly.

Maybe something like PowerMock directly supports mocking a private variable. I'm not sure. I also doubt that it is worth the trouble.

I hope this helps,

Eric 

Le mercredi 30 janvier 2013, Serguei Cambour a écrit :
I did'nt find the answer for the above question, so sorry if it was already solved somewhere. As far as I could see, Mockito does not do that.
My question is how to mock/spy a class in which a private statis logger variable declared as follows:

class MyClassToMock {
  private static AppLogger appLogger = UtilLogger.getLogger();

... other provate variables ad methods
}

Thank you in advance;

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

J.

unread,
Jan 30, 2013, 4:30:14 PM1/30/13
to moc...@googlegroups.com
Assuming I want to check logging and AppLogger can be mocked (i.e. interface or no final methods used) I usually do something like

class MyClassToMock {
  final private static AppLogger staticAppLogger = UtilLogger.getLogger();
  final private AppLogger appLogger = UtilLogger.getLogger();

  protected  MyClassToMock(AppLogger logger){
    this.appLogger = logger;
  }

  public MyClassToMock(){
    this(staticAppLogger);
  }

then I can MyClassToMock using protected constructor for unit tests

Kornel Kiełczewski

unread,
Feb 1, 2013, 10:56:34 AM2/1/13
to moc...@googlegroups.com
Using a constructor seems like a good approach. I'd suggest making this constructor package scope, which is even better than protected.

Another thing is, should we test logger calls? Maybe the logging class does sth more than 'simple' logging? Which on the other hand depends what simple is..

Could you please give an example when we should test a logger?

Tomek Kaczanowski

unread,
Feb 1, 2013, 11:04:13 AM2/1/13
to moc...@googlegroups.com
@Kornel, sometimes logging is an important business feature and as
such should be tested. GOOS book discusses this subject (if I remember
correctly).

--
Regards / Pozdrawiam
Tomek Kaczanowski
http://practicalunittesting.com

Eric Lefevre-Ardant

unread,
Feb 1, 2013, 11:07:24 AM2/1/13
to moc...@googlegroups.com
I agree, a package-friendly constructor would be more appropriate. I also frequently mark those constructors with @VisibleForTesting.

Testing logger calls : a good question. I think everyone has their own rule of thumb for that. Mine is that I test anything that is displayed to the user (that was the case of some of the logs on my last project), plus all logs of level ERROR and above. The other levels are not very interesting.

Of course, as the guys from GOOS would say, if your logging is important, then you probably need to extract it into a separate class that you own, which makes it more obvious that you need to test interactions.


--

Brice Dutheil

unread,
Feb 1, 2013, 11:32:01 AM2/1/13
to moc...@googlegroups.com

On Fri, Feb 1, 2013 at 5:07 PM, Eric Lefevre-Ardant <er...@ericlefevre.net> wrote:
Of course, as the guys from GOOS would say, if your logging is important, then you probably need to extract it into a separate class that you own, which makes it more obvious that you need to test interactions.

I was about to propose that, Logger is a technical class it's the "technical implementation" of how you will log things. But if your business use case is to log then you should have a class that represent that feature, even methods with dedicated names that will delegate to your Logger or something else. This class and methods will express what appear in the "business language".

 

-- Brice

J.

unread,
Feb 3, 2013, 8:15:56 AM2/3/13
to moc...@googlegroups.com

Some instances when I might want to test things are logged


  1. the spec calls for specific entries to appear in the log for automatic monitoring purposes.

  2. when something goes wrong because of a data error – to check a reference/item identifier is written to log so support can go straight to the item and look for the data error rather than having to check all items in batch/waiting to be processed.


Other than specific requirements I think you should generally ignore logging in unit tests (other than to make sure each log call is run on unit tests – especially if using something like String.format to build error messages) -  One irritation I recall is someone using JMock (IIRC) religiously checking what logging was happening and the framework throwing an error if you accessed it more times than defined – a pita when you wanted to add extra information during testing to see what was happening (didn't take long to allow all)

Serguei Cambour

unread,
Feb 4, 2013, 10:29:55 AM2/4/13
to moc...@googlegroups.com
Thank you all, guys, for the replies. Sure, as I could find out later, Mockito didn't support mocking final and static methods/variables. I'll takea try with powermock.
@J: the way you propose suppose to modify the class to be tested what is impossible in my case, I just can not add one more constructor or logger instance to be abel just to mock the class.

Thanks & Regards
Reply all
Reply to author
Forward
0 new messages