2

I have a library, built with Maven, that uses Spring 4.0.3.RELEASE and Togglz 2.2.0.Final. I'm trying to write a JUnit 4.11 test of my Spring class and running into the following error on the first test that gets executed:

testCreateItem_throwsItemServiceBusinessException(impl.ItemServiceImplTest)  Time elapsed: 1.771 sec  <<< ERROR!
java.util.ServiceConfigurationError: org.togglz.core.spi.LogProvider: 
Provider org.togglz.slf4j.Slf4jLogProvider not a subtype

Here is the relevant java test snippet:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class)
@PrepareForTest({ ItemServiceImpl.class })
public class ItemServiceImplTest {
   @Rule
   public TogglzRule togglzRule = TogglzRule.allDisabled(Features.class);

   @Rule
   public PowerMockRule powerMockRule = new PowerMockRule();

   @Test(expected = ItemServiceBusinessException.class)
   public void testCreateItem_throwsItemServiceBusinessException() throws Exception {
      PowerMockito.doReturn(mockMetricsData).when(serviceUnderTest, START_METRICS_METHOD_NAME, any(MetricsOperationName.class), any(RequestContext.class));

      when(mockDao.createItem(any(Item.class), any(RequestContext.class))).thenThrow(dataBusinessException);

      serviceUnderTest.createItem(item, context);

      verify(mockItemServiceValidator).validate(any(Item.class), any(RequestContext.class));

      PowerMockito.verifyPrivate(serviceUnderTest).invoke(START_METRICS_METHOD_NAME, any(MetricsOperationName.class), any(RequestContext.class));

      verify(mockDao).createItem(any(Item.class), any(RequestContext.class));
   }
}

Subsequent test calls get the following error:

java.lang.NoClassDefFoundError: Could not initialize class org.togglz.junit.TogglzRule

Here are some relevant dependencies I have:

 org.mockito:mockito-all=org.mockito:mockito-all:jar:1.9.5:compile,
 org.powermock:powermock-module-junit4=org.powermock:powermock-module-junit4:jar:1.5.6:test,org.powermock:powermock-module-junit4-common=org.powermock:powermock-module-junit4-common:jar:1.5.6:test,
 org.powermock:powermock-reflect=org.powermock:powermock-reflect:jar:1.5.6:test,
 org.powermock:powermock-api-mockito=org.powermock:powermock-api-mockito:jar:1.5.6:test,
 org.powermock:powermock-api-support=org.powermock:powermock-api-support:jar:1.5.6:test,
 org.powermock:powermock-module-junit4-rule=org.powermock:powermock-module-junit4-rule:jar:1.5.6:test,
 org.powermock:powermock-classloading-base=org.powermock:powermock-classloading-base:jar:1.5.6:test,
 org.powermock:powermock-core=org.powermock:powermock-core:jar:1.5.6:test,
 org.powermock:powermock-classloading-xstream=org.powermock:powermock-classloading-xstream:jar:1.5.6:test,
 org.togglz:togglz-core=org.togglz:togglz-core:jar:2.2.0.Final:compile,
 org.togglz:togglz-slf4j=org.togglz:togglz-slf4j:jar:2.2.0.Final:compile,
 org.togglz:togglz-spring-core=org.togglz:togglz-spring-core:jar:2.2.0.Final:compile,
 org.togglz:togglz-testing=org.togglz:togglz-testing:jar:2.2.0.Final:test,
 org.togglz:togglz-junit=org.togglz:togglz-junit:jar:2.2.0.Final:test

And I have provided a LogProvider (org.togglz.slf4j.Slf4jLogProvider) via SPI, located at META-INF/serivces/org.togglz.core.spi.LogProvider

This error is baffling as Slf4jLogProvider should be assignable from LogProvider. Sorry for the verbosity, but I wanted to try and show a complete picture. The code in class "under test" is making a call to see if a single feature is enabled inside the create method.

B. Mericle
  • 23
  • 4

1 Answers1

-1

First of all: You don't need to configure the log provider in your application. Including togglz-slf4j on your application path is sufficient because this jar contains the corresponding SPI file.

Could you please check if there are multiple conflicting versions of the Togglz JAR files on your classpath? For example using togglz-core-2.2.0.Final.jar together with togglz-slf4j-2.1.0.Final.jar could result in an error like this.

This can happen if you update Togglz and your IDE didn't remove the old archives. Running a clean build and/or selecting "Update Maven Configuration" on Eclipse will fix this problem.

chkal
  • 5,598
  • 21
  • 26
  • 1
    That was the first thing I checked. I even removed togglz from my .m2 repository and rebuilt to make sure no other version was being brought in. I also thought just including the slf4j module would automatically add it as a provider, but the initial error I got was: "testCreateItem_throwsItemServiceBusinessException(impl.ItemServiceImplTest) Time elapsed: 1.771 sec <<< ERROR! java.util.ServiceConfigurationError: org.togglz.core.spi.LogProvider: Provider org.togglz.core.logging.Jdk14LogProvider not a subtype" Which also doesn't make any sense. – B. Mericle Jun 28 '16 at 16:11
  • I wonder if PowerMock is messing with the classloader? I know it instruments classes, but it shouldn't instrument the togglz classes. – B. Mericle Jun 28 '16 at 16:14
  • Hmmm. That's weird. It may be possible that instrumentation is causing this. I guess you could try to do some debugging in the corresponding classes to find out what is going wrong. Or you could try to call ServiceLoader.load(LogProvider.class) yourself in a minimal test with and without Powermock – chkal Jun 28 '16 at 19:07
  • 1
    Removing PowerMock from the equation solved the problem. I needed to refactor my code a little to get rid of it, but in the end it made the code better, so it's all good now. – B. Mericle Jul 01 '16 at 15:37
  • Adding @PowerMockIgnore({"org.mockito.*", "org.togglz.*"}) to class helped me to solve this issue. – Master Drools Mar 17 '17 at 13:05