Reputation: 432
I want to mock an object with Mockito of a class that has some irrelevant static methods.
There are many questions here on stack overflow that explain that mocking static methods is not possible with Mockito. However, the static methods of the object that I need in my unit test are irrelevant for the test.
More concretely, I want to write a unit test for a method that looks for documents in a cache and in case of a cache miss loads them from a Couchbase lite database. Unfortunately the com.couchbase.lite.Document class has some static methods and trying to mock them
Document mockDocument = Mockito.mock(Document.class);
results in a java.lang.UnsatisfiedLinkError
.
I intend to mock some of the non-static methods e.g.
doReturn("SomeString").when(mockDocument).getString("someKey");
but the static methods are never used, neither in the tested method nor in the unit test itself. Concerning Couchbase, I guess that the library is not particularly relevant for my question, just the fact that I want to mock an object of some library class which contains both, irrelevant static as well as relevant non-static methods.
Update: Here is the stack trace
java.lang.UnsatisfiedLinkError: com.couchbase.lite.internal.core.C4Log.setLevel(Ljava/lang/String;I)V
at com.couchbase.lite.internal.core.C4Log.setLevel(Native Method)
at com.couchbase.lite.FileLogger.setupDomainObjects(FileLogger.java:84)
at com.couchbase.lite.FileLogger.<init>(FileLogger.java:47)
at com.couchbase.lite.Log.<init>(Log.java:35)
at com.couchbase.lite.AbstractDatabase.<clinit>(AbstractDatabase.java:80)
at com.couchbase.lite.internal.support.Log.sendToLoggers(Log.java:401)
at com.couchbase.lite.internal.support.Log.e(Log.java:247)
at com.couchbase.lite.NativeLibraryLoader.load(NativeLibraryLoader.java:41)
at com.couchbase.lite.Document.<clinit>(Document.java:42)
at sun.reflect.GeneratedSerializationConstructorAccessor10.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
at org.objenesis.ObjenesisBase.newInstance(ObjenesisBase.java:73)
at org.mockito.internal.creation.instance.ObjenesisInstantiator.newInstance(ObjenesisInstantiator.java:19)
at org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker.createMock(SubclassByteBuddyMockMaker.java:47)
at org.mockito.internal.creation.bytebuddy.ByteBuddyMockMaker.createMock(ByteBuddyMockMaker.java:25)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:35)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:63)
at org.mockito.Mockito.mock(Mockito.java:1910)
at org.mockito.Mockito.mock(Mockito.java:1819)
at com.my.app.ClassOfTheTest.nameOfTheTest(ClassOfTheTest.java:1234)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
Upvotes: 3
Views: 6245
Reputation: 2113
Create a DocumentUtils class for these static methods, that way if you wanted to use these methods in the UnitTest you can still do so without mocking it.
DocumentUtils.someMethod(args);
Update:
How the DocumentUtils class may look like (Added some imaginary static methods that likely have no relevance to your use-case) :
public final class DocumentUtils {
public static boolean isDocumentReadable(Document doc) {
...
}
public static boolean isDocumentWrittenInEnglish(Document doc) {
...
}
public static List<Document> getEnglishWrittenDocuments(List<Document> docs) {
...
}
public static boolean areDocumentsTheSame(Document doc1, Document doc2) {
...
}
}
Tests:
When it comes to testing you may not even need to reference this class at all...
You will however, need to ensure the mocked Document object that is going to be passed to these methods one way or another, will return the expected value.
For example, if DocumentUtils.isDocumentWrittenInEnglish(Document doc)
were to be called at some stage, the mock has to be setup to return the expected value beforehand:
when(mockedDocument.getLanguage()).thenReturn(LANGUAGE_ENGLISH);
Upvotes: 2