微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决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 举报,一经查实,本站将立刻删除。