【问题标题】:How to mock Abstract class method in a class to be tested如何在要测试的类中模拟抽象类方法
【发布时间】:2020-01-01 17:41:07
【问题描述】:

有一个abstract 类

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

还有一个 final class 将使用 Junit 进行测试

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;
}
}

我尝试spying BaseProcessor 类和模拟 getBooksTransaction 方法到return 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 对象。 它既不会抛出exception,也不会抛出任何error。

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

我是Mockito 的新手,任何帮助都将不胜感激。 提前致谢。

【问题讨论】:

  • 默认不支持模拟最终类,但如果您使用支持此功能的模拟版本,则可以启用。请改用answer 和/或faq。
  • @second that final class 将导致非常具体的错误消息; OP 没有得到。

标签: java unit-testing mockito junit4 spy


【解决方案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!");
}

现在想想,你在评论中说://method to be tested 但你甚至没有在你的测试中调用它,听起来很可疑不是吗?该方法在CreateOrganisationProcessor 中定义,但您将间谍分配给:

 BaseProcessor spy = Mockito.spy(new CreateOrganisationProcessor());

所以现在你甚至不能再在 spy 引用上调用 process,因为它没有在 BaseProcessor 中定义。

【讨论】:

  • 我没有添加 assert 声明,我正在调用进程以保持问题简短。在调用 process 方法之前还有很多模拟要做。但是第一行getBooksTransaction 抛出了错误,这让我提出了这个问题。我看到spy 是在CreateOrganisationProcessor 而不是BaseProcessor 上创建的,spy 背后的概念是什么?你能简单解释一下吗?此外,当我运行此代码时,它会抛出NPE。在getBooksTransaction()。当我评估 intellij 中的表达式时,它说“this”不可用。
  • @NiharikaDash 看看你有多大意义。一方面,您说 但第一行 getBooksTransaction 抛出错误,这让我在评论中提出问题,但您在问题中说:它既不抛出异常,也不抛出任何错误。 然后你继续说:另外,当我运行此代码时,它会抛出 NPE,然后是_当我在 intellij 中评估表达式时,它说“this”不可用。。您在谈论 10 种不同的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-05
  • 1970-01-01
  • 2018-09-23
  • 1970-01-01
  • 2011-01-24
相关资源
最近更新 更多