I have a class that writes messages to some magazines. A class is a utility that does nothing; it runs in the background, checks for several things, and writes them to the log. I am wondering if it is possible for me to check in the unit test that the log was written without worrying about what it actually writes. Here my class is tested:
//imports... public class MyClass { private static Log log = LogFactory.getLog(MyClass.class); public MyClass() { log.info("MyClass is being created."); } public void doThing() { if( everything_is_fine ) { log.info("This is a message to say everything is fine."); } else { log.error("Uh oh..."); } } }
And my tester class:
// imports ... @RunWith(PowerMockRunner.class) @PrepareForTest({MyClass.class,LogFactory.class}) public class MyClassTest { Log mockLog; @Before public void setup() { PowerMockito.mockStatic(LogFactory.class); mockLog = mock(Log.class); PowerMockito.when(LogFactory.getLog(MyClass.class)).thenReturn(mockLog); } @Test public void test_everything_is_ok() { MyClass mything = new MyClass(); // should write to log.info mything.doThing(); // should write to log.info verify(mockLog, atLeastOnce()).info(anyString()); verify(mockLog, never()).error(anyString()); } @Test public void test_everything_is_not_ok() { MyClass mything = new MyClass(); // should write to log.info // do something which makes things not ok mything.doThing(); // should write to log.error verify(mockLog, atLeastOnce()).info(anyString()); verify(mockLog, atLeastOnce()).error(anyString()); } }
When I run the tests, I expect log.info () to be called for both tests, and log.error () to be called only for the second. However, I get "Wanted but not called" for log.info for both tests. and for log.error on the second. So either:
1) My code is broken and not logged, or
2) My test is broken.
I think I messed up something in my test, maybe something really obvious, so did anyone experience something like this that could help me? Any help would be appreciated.
UPDATE:
Thanks to those who helped, I now have a solution.
After playing a bit with the code, I found that there seems to be a problem with initializing the log. Doing private static Log log = LogFactory.getLog(MyClass.class); didn't seem to use the layout correctly, so if I translate it into the constructor, it seemed like it was taunted, and my tests all work as expected:
public class MyClass { private static Log log; public MyClass() { MyClass.log = LogFactory.getLog(MyClass.class); log.info("MyClass is being created."); }
It works for me now, but can anyone explain why the initialization of the log in the first way did not work? Or perhaps point me somewhere that explains this? I am not sure if there is a gap in my understanding of how Java initializes objects or if this is a limitation of mocking frameworks.