DEV Community

John Mercier
John Mercier

Posted on

10 2

Mocking private static final log

Tests for logging is something I have tried to avoid in the past. Today I had to write some code which exports TestRail results to splunk and I was determined to test the output.

Instead of searching for how to do this using jmockit or mockito (since this hasn't worked for me in the past) I decided to try using reflection myself. I searched for "java reflection change private static field" and came across this post on stackoverflow. The post shows a way to change the value of a public static final field. There are some caveats but in the case of Logger it works out.

Combining this information with mockito I was able to mock the logger for a class and test logging output. First the test setup (junit 4.13):

@RunWith(MockitoJunitRunner.class)
public class SplunkReporterMethods {
  @Mock private Logger log;
  private SplunkReporter reporter;

  @Test
  public void report() {
    reporter.report(new Car());
    then(log).should().info("{\"name\":\"car\",\"speed\":4}");
  }
}

To setup the SplunkReporter class with a different logger the mock needs to be injected into the private static final field. This can be done in an @Before method.

@Before
void setup() {
  //allow log field to be changed
  Field field = SplunkReporter.class.getDeclaredField("log");
  field.setAccessible(true);

  //remove final modifier
  Field modifiersField = Field.class.getDeclaredField("modifiers");
  modifiersField.setAccessible(true);
  modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

  //set to mock object
  field.set(null, log);
  reporter = new SplunkReporter();
}

First, the setup method makes log accessible but that is not enough. The modifiers on the field need to be changed so final is removed. The Field class does not have a setter for the modifiers field and so modifiers needs to be set in field using reflection. Finally the static field is set to the mock object.

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay