簡體   English   中英

如何驗證 java.lang.reflect.Method 僅從反射已知被調用在 object

[英]How to verify a java.lang.reflect.Method known only from reflection was called on an object

給定通過反射獲得的 java.lang.reflect.Method object,我如何測試在給定的 object 上調用了此方法?

這是一個示例代碼:

MyClass obj = mock(MyClass.class);
injectInTestedObject(obj, testedObj);

String myMethodIWantToCheckName = retrieveMethodNameBySomeMeans();
Method myMethodIWantToCheck =
  Arrays.asList(MyClass.class.getMethods())
    .stream()
    .filter(method -> method.getName().equals(myMethodIWantToCheckName))
    .findFirst()
    .get();

現在我想檢查是否在obj上調用了myMethodIWantToCheck

基本上它與 Mockito 的verify功能相同,但在編譯時不知道該方法。

有什么辦法嗎? 任何圖書館已經實現了這個?

不,顯然沒有簡單的方法可以僅使用 Java SE 提供的庫。 我對此感到非常高興!

天真的方法

讓我們想象一下,您要實現的目標實際上是可能的,並且在java.lang.reflect中支持操作。 提供這樣的功能需要什么樣的信息和機制? 如果一個人應該能夠在任何時候檢索某個方法是否已經被調用(在某個對象上)至少一次(沒有“開始分隔符”),則需要 Java 虛擬機來跟蹤任何調用; 有效地強制它保留所有創建的堆棧幀,引入這樣的起始分隔符可能會減少運行時開銷,但仍需要極其復雜的堆棧幀審計形式。 內置在每個 JVM 中。

Mockito 是如何做到的

但是,嘿,Mockito 能夠提供這樣的功能,對吧? 確實,但我認為你低估了他們這樣做的方式的復雜性。

首先,您的方法和 Mockito 的方法之間存在一個非常重要的概念差異。 在查看Mockito 網站上的第一個示例時,已經很明顯了:

import static org.mockito.Mockito.*;

// mock creation
List mockedList = mock(List.class);

// using mock object - it does not throw any "unexpected interaction" exception
mockedList.add("one");
mockedList.clear();

// selective, explicit, highly readable verification
verify(mockedList).add("one");
verify(mockedList).clear();

框架的用戶總是必須首先模擬感興趣的類型; 要么明確地喜歡這里,要么通過使用注釋以更隱含的方式。 由於我對 Mockito 框架不是很熟悉,因此可能有更優雅的方法可以做到這一點; 但這一切都歸結為同一個概念。

但是“模擬類型”甚至意味着什么,它應該有什么用處? 實際上,Mockito 必須以某種方式攔截對 mocking 方法(或其他機制)返回的 object 進行的任何調用。 幸運的是(記住這篇文章的開頭),Mockito 不能直接這樣做,所以開發人員必須想出別的辦法:在運行時動態創建新類型,不僅將方法調用委托給實際實現,但它也跟蹤在該特定類型上調用的方法。

查看框架的源代碼,似乎真正的魔力發生在org.mockito.internal.creation.bytebuddy package 中。 SubclassBytecodeGenerator中,您可以找到 Mockito 的類型創建邏輯。 正如 package 名稱已經暗示的那樣,Mockito 使用Byte Buddy 框架進行字節碼生成和加載過程。

圖書館支持

正如您還要求提供一個可以用來實現相同行為的庫:據我所知,那里沒有真正知名的庫

老實說:我對這種情況並不感到驚訝。 我的意思是,一個人應該使用這樣的圖書館做什么? 檢查方法是否被調用是測試中應該做的事情; 其他用例非常有限。

是的。 我想你的選擇非常有限。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM