【问题标题】:How do I test interactions with private fields of a class with unit testing on java? [duplicate]java - 如何通过Java上的单元测试来测试与类的私有字段的交互? [复制]
【发布时间】:2018-08-25 08:15:16
【问题描述】:

我有以下课程

public class BookProcessor {

    private Map<String, Double> bookToValueRecord = new HashMap<>();
    private Map<String, Integer> bookToCountRecord = new HashMap<>();
    private int counter = 0;

    public void processBook(Book book) {
        counter++;
        recordBook(book);
        if (counter % 5 == 0) {
            printSomeReport();
        } if (counter % 10 == 0) {
            printAnotherReport();
        }
    }

    private void printAnotherReport() {
       //just print something
    }


    private void printSomeReport() {
        //print something else here
    }

    private void recordBook(Book book) {
        bookToValueRecord.put(book.getTitle(), book.getValue());
        bookToCountRecord.put(book.getTitle(), bookToCountRecord.getOrDefault(book.getProduct(), 0)+book.getCount());
    }
}

我的想法是创建一个带有字段BookProcessor testee; 的测试类BookProcessorTest 我不知道是否需要模拟它?我的一项测试将是shouldProcessBook()。在这个测试中,我将创建一个示例Book 对象,然后我将调用testee.processBook(myBookObject),但是我应该断言或验证什么?我是否应该检查此记录是否已保存到bookToValueRecord?如果是,鉴于这是一个私有字段,如何? 另外,如何在将 5 本书保存到我的 Map 后进行测试,我正在打印一些报告?我应该测试printSomeReport() 是否已被调用?如果是,那么如何考虑printSomeReport私有方法

【问题讨论】:

    标签: java unit-testing testing junit mocking


    【解决方案1】:

    关于如何测试你的课程:

    1) 您需要模拟,因为被测类有一些需要隔离的依赖项。
    但是您没有任何依赖项可以在那里模拟。

    2) private 方法不应被测试,您也不应检查这些方法是否在测试期间被调用。
    这些是 API 的实现细节:公共方法processBook()

    3) 只有通过注意到副作用的方法才能测试不返回任何内容但会产生副作用的 API。你好像没有这个。

    那又怎样?
    实际上,您被卡住了,因为a)您的班级做了太多事情,b)您的班级存储了一些东西,但没有提供检索这些东西的方法。

    a) private 方法 printAnotherReport()printSomeReport() 实际上应该移动到实际缺失的依赖关系的 public 方法中。例如,引入 PrintService 类会有所帮助。
    通过这种方式,您可以模拟它,并且可以检查这些方法是否按预期调用。例如将类更新为:

    private PrintService printService; // dependency 
    
    BookProcessor (PrintService printService){
       this.printService = printService;
    }
    

    b) 关于recordBook() private 方法,如果BookProcessor 编写了一些书(因此BookProcessor 在这里可能不是一个方便的名称),BookProcessor 也应该提供检索它们的方法。
    因此,似乎需要添加 public 方法来检索添加的信息。
    但请注意,您不必打破Maps 的封装,您可以提供从作为参数传递的键中检索值的方法:

    public Double getValue(String key){
        return bookToValueRecord.get(key); 
    }
    
    public Integer getCount(String key){
        return bookToCountRecord.get(key); 
    }
    

    【讨论】:

      猜你喜欢
      • 2016-10-25
      • 2013-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      相关资源
      最近更新 更多