如何在要测试的类中模拟抽象类方法

5

有一个抽象

public abstract class BaseProcessor {
 public BooksTransaction getBooksTransaction() {
        return booksTransaction;
    }
}

还有一个需要使用Junit测试的final class

public final class CreateOrganisationProcessor extends BaseProcessor {

public boolean process() throws Exception { //method to be tested
        request = new CreateOrganisationRequest(IntegrationSystems.valueOf(getBooksTransaction().getSource()),
                IntegrationSystems.valueOf(getBooksTransaction().getDestination()), getBooksTransaction()); 
        request.setRequestTypes(getRequestTypes());
return true;
}
}

我尝试着窥视BaseProcessor类,并模拟getBooksTransaction方法,使其返回BooksTransaction对象代码:

@Test
   public void testProcess() throws Exception {
BaseProcessor spy = Mockito.spy(new CreateOrganisationProcessor());
       BooksTransaction booksTransaction = new BooksTransaction();
       booksTransaction.setReferenceID(DEFAULT_REFERENCE_ID);
       Mockito.doReturn(booksTransaction).when(spy).getBooksTransaction();
}

在这里,BooksTransaction是一个JPA Entity类。

然而,当我运行测试案例时,模拟似乎没有起作用,它没有返回一个BooksTransaction对象。 它既没有抛出异常,也没有任何错误

我想知道正确的spy方法,以便根据我的mock返回一个BooksTransaction对象。

我对Mockito很新,任何帮助都将不胜感激。 谢谢提前。


默认情况下不支持对final类进行模拟,但是如果您使用支持此功能的Mockito版本,则可以启用它。请查看此答案和/或faq - second
我赞同final类会导致一个非常具体的错误消息;而这个错误消息OP并没有得到。 - Eugene
1个回答

1

有趣的是,你的问题甚至无法编译,却得到了5个赞...我稍微简化了一下,这样我就可以实际编译它了,因为我不知道你的结构,甚至无法正确猜测。

但你应该知道的第一件事是,Mockito不能默认地模拟final类;你在问题下面的评论中展示了如何启用它。

@Getter
static abstract class BaseProcessor {
    private BooksTransaction BooksTransaction;
}

@Getter
static class CreateOrganisationProcessor extends BaseProcessor {

    CreateOrganisationRequest request;

    public boolean process() { //method to be tested
        request = new CreateOrganisationRequest(getBooksTransaction());
        return true;
    }

    public CreateOrganisationRequest getRequest() {
        return request;
    }
}


@RequiredArgsConstructor
@Getter
static class BooksTransaction {
    private final String testMe;
}

@Getter
@RequiredArgsConstructor
static class CreateOrganisationRequest {
    private final BooksTransaction booksTransaction;
}

这里有一个测试可以正常运行

@Test
public void test() {
    CreateOrganisationProcessor org = new CreateOrganisationProcessor();
    CreateOrganisationProcessor spy = Mockito.spy(org);
    System.out.println(spy);
    BooksTransaction booksTransaction = new BooksTransaction("go!");

    Mockito.doReturn(booksTransaction).when(spy).getBooksTransaction();

    spy.process();
    BooksTransaction mocked = spy.getRequest().getBooksTransaction();
    Assert.assertEquals(mocked.getTestMe(), "go!");
}

现在想一想,你在评论中说://需要测试的方法但是你甚至没有在测试中调用它,听起来很可疑,对吧?那个方法定义在CreateOrganisationProcessor中,但是你把间谍分配给了:
 BaseProcessor spy = Mockito.spy(new CreateOrganisationProcessor());

现在你甚至不能在那个 spy 引用上调用 process,因为它在 BaseProcessor 中未被定义。


我在调用process的地方没有添加assert语句,以保持问题简短。在调用process方法之前还有很多模拟需要完成。但是第一行getBooksTransaction抛出了错误,这让我提出了问题。我看到在CreateOrganisationProcessor上创建了spy而不是在BaseProcessor上,这背后的概念是什么?能否简要解释一下?此外,当我运行此代码时,它会抛出NPE异常,在getBooksTransaction()处。当我在IntelliJ中评估表达式时,它说'this'不可用。 - Niharika Dash
@NiharikaDash 看看你说的有多少道理。一方面,你在评论中说“但是getBooksTransaction的第一行抛出了错误,这让我提出了问题”,但是你在问题中说:“它既不抛出异常,也不报错。”然后你又说:“此外,当我运行这段代码时,它会抛出NPE,接着是‘当我在intellij中评估表达式时,它说'this'不可用’”。你说了10个不同的事情。 - Eugene

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接