JMockit 在第二次测试调用时返回真实类而不是模拟对象

问题描述

我目前正在使用 JUnit 5 和 JMockit 1.49 增加遗留代码代码覆盖率。

我有一个测试类,它有两个单独的测试方法

class CodatixBookmarkControllerTest {
    @Tested
    CodatixBookmarkController bookmarkController;
    
    @Mocked
    ServiceLocator locator;
    @Mocked
    HttpServletRequest req;
    @Mocked
    HttpServletResponse res;
    @Mocked
    DMSFolder folder;
    
    @Test
    void testShowBookmarksNoExistingBookmarksFolder() throws IOException {
        List<DMSFolder> folderList = new LinkedList<DMSFolder>();
        folderList.add(folder);
        
        new Expectations() {
            {
                folder.listContents();
                returns(Collections.EMPTY_LIST,folderList);
                folder.getName();
                result = Globals.BOOKMARKS_FOLDER_NAME;
                folder.getKey();
                result = "key";
                
            }
        };
        
        bookmarkController.showBookmarks(req,res);
        
        new Verifications() {
            {
                folder.listContents();
                times = 2;
                folder.add((DMSObject)any);
                times = 1;
            }
        };
        
    }
    
    
    @Test
    void testShowBookmarsExistingBookmarksFolder() throws IOException {
        List<DMSFolder> folderList = new LinkedList<DMSFolder>();
        folderList.add(folder);
        
        new Expectations() {
            {
                folder.listContents();
                result = folderList;
                folder.getName();
                result = Globals.BOOKMARKS_FOLDER_NAME;
                folder.getKey();
                result = "key";
            }
        };
        
        bookmarkController.showBookmarks(req,res);
        
        new Verifications() {
            {
                folder.listContents();
                times = 1;
                folder.add((DMSObject)any);
                times = 0;
            }
        };
        
    }
    
}

它们几乎相同,只是期望块和验证块不同。当我使用 Eclipse 运行该类时,在 second 方法上出现以下错误

java.lang.classCastException: java.lang.class incompatible with com.groiss.dms.DMSFolder
    at ch.iflow.codatix.CodatixBookmarkController.getBookmarksFolder(CodatixBookmarkController.java:153)
    at ch.iflow.codatix.CodatixBookmarkController.showBookmarks(CodatixBookmarkController.java:85)
    at ch.iflow.codatix.CodatixBookmarkControllerTest.testShowBookmarsExistingBookmarksFolder(CodatixBookmarkControllerTest.java:82)

错误是在下面代码片段的最后一行被测试的类中抛出的:

    private DMSFolder getBookmarksFolder(User user) {
        DMSFolder folder = null;
        DMSFolder rootFolder = dms.getRootFolder(user);

正如错误所暗示的那样,getRootFolder()-Method 返回类型为 Class 而不是 DMSFolder 的对象。但是,dms 是被测类的一个类字段,并从模拟的 ServiceLocator 实例化,因此根据我的理解,它也应该返回一个模拟的 DMSFolder 实例。

奇怪的是,如果测试类中只存在两者中的一个测试方法,则它们都成功并且测试通过。每当有两种方法同时存在时,最后一种就会因为上述错误而失败。

在调试时,我看到在 JMockit 的 RecordandReplayExecution.java 类中,选择了认返回值而不是模拟实例:

@Nonnull Object[] mockArgs = args == null ? NO_ARGS : args;
      ExecutionMode executionMode = ExecutionMode.values()[executionModeOrdinal];

      if (nottoBeMocked(mock,classDesc)) {
         // This occurs if called from a custom argument matching method,in a call to an overridden Object method (equals,hashCode,// toString),from a different thread during recording/verification,or during replay but between tests.
         return defaultReturnValue(mock,classDesc,mockDesc,genericSignature,executionMode,mockArgs);
      }

有人知道为什么会这样吗?我是否犯了概念性错误?还是我以错误的方式使用 JMockit?

非常感谢任何帮助,谢谢!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)