Class that has private static non final field
package sample;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class App {
private static Logger logger = LoggerFactory.getLogger(App.class);
public void doSomething() {
logger.error("Cannot do something");
}
}
Attempt to set this field through reflection
package sample;
import org.apache.logging.log4j.core.Logger;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import static org.mockito.Mockito.mock;
public class AppTest {
@Test
public void doSomething() throws Exception {
App app = new App();
Logger mockedLogger = mock(Logger.class);
ReflectionTestUtils.setField(App.class, "logger", mockedLogger);
}
}
results in IllegalArgumentException
Can not set static org.slf4j.Logger field sample.App.logger to org.apache.logging.log4j.core.Logger$MockitoMock$1185285221
java.lang.IllegalArgumentException: Can not set static org.slf4j.Logger field sample.App.logger to org.apache.logging.log4j.core.Logger$MockitoMock$1185285221
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
at sun.reflect.UnsafeStaticObjectFieldAccessorImpl.set(UnsafeStaticObjectFieldAccessorImpl.java:79)
at java.lang.reflect.Field.set(Field.java:764)
at org.springframework.util.ReflectionUtils.setField(ReflectionUtils.java:633)
According to JavaDocs of invoked method
Set the static field with the given name on the provided targetClass to the supplied value.
setting static field is supported.
Since the IllegalArgumentException is thrown by java.lang.reflect.Field.set
according to the stack trace, the javadoc for Field.set can be consulted as to the reason.
It states:
IllegalArgumentException - if the specified object is not an instance of the class or interface declaring the underlying field (or a subclass or implementor thereof), or if an unwrapping conversion fails.
Comparing your provided App and AppTest classes reveals that AppTest imports org.apache.logging.log4j.core.Logger
whereas App imports org.slf4j.Logger
Since you are trying to inject a mock of the logger, change the first import in AppTest to org.slf4j.logger
.