简体   繁体   English

Mockito 模拟具有无关静态方法的类

[英]Mockito mock a class that has irrelevant static methods

I want to mock an object with Mockito of a class that has some irrelevant static methods.我想用 Mockito 模拟一个具有一些不相关静态方法的类的对象。

There are many questions here on stack overflow that explain that mocking static methods is not possible with Mockito.这里有很多关于堆栈溢出的问题,解释了 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.更具体地说,我想为在缓存中查找文档的方法编写单元测试,并在缓存未命中的情况下从 Couchbase lite 数据库加载它们。 Unfortunately the com.couchbase.lite.Document class has some static methods and trying to mock them不幸的是 com.couchbase.lite.Document 类有一些静态方法并试图模拟它们

Document mockDocument = Mockito.mock(Document.class);

results in a java.lang.UnsatisfiedLinkError .导致java.lang.UnsatisfiedLinkError I intend to mock some of the non-static methods eg我打算模拟一些非静态方法,例如

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.关于 Couchbase,我想该库与我的问题并不是特别相关,只是我想模拟某个库类的对象,其中包含不相关的静态方法和相关的非静态方法。

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)

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 类,这样如果您想在 UnitTest 中使用这些方法,您仍然可以这样做而无需模拟它。

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) : DocumentUtils 类的外观(添加了一些可能与您的用例无关的虚构静态方法)

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.但是,您需要确保以一种或另一种方式传递给这些方法的模拟 Document 对象将返回预期值。

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:例如,如果在某个阶段调用DocumentUtils.isDocumentWrittenInEnglish(Document doc)则必须事先设置模拟以返回预期值:

when(mockedDocument.getLanguage()).thenReturn(LANGUAGE_ENGLISH);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM