Andreas Dolk
Andreas Dolk

Reputation: 114817

How to use InjectMocks if the instance to be injected has a final class

I want to test some services with mockito. The services are based on CDI and, unfortunately, use field injection, which I can't change.

public class Service {
   @Inject Logger logger;

   public void method() {
      logger.info("some log text");
  }
}

Now it is quite easy to create the testable instances with mockito's @InjectMocks annotation. It will inject either mocks and spies.

@RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
  @Spy Logger logger = LoggerFactory.getLogger(Service.class);

  @InjectMocks Service service;

  @Test public void test() {
     // Given
     // When
     service.method();
     // Then
  }

I need some working logger injected into my service class under test. The logger framework is slf4j, the preferred logger is logback. But unfortunately again, logback's implementation of Logger is final, so I can't spy on that, it results in a runtime exception.

Workarounds, that come to my mind:

But is there a clean or at least better solution for that (those) problem(s)?

Upvotes: 8

Views: 2487

Answers (1)

Rogério
Rogério

Reputation: 16390

Your class under test is most likely using Logback incorrectly. Instead of declaring the logger field as being of type ch.qos.logback.classic.Logger, it should be the interface type org.slf4j.Logger, which is implemented by the final Logback logger class.

That way, you avoid the issue since there is no final class to be mocked or injected.

Upvotes: 2

Related Questions