如何使用 Junit 4.x 測試 私有方法?

開篇

  好久不發技術博客,今年要撿起來,新年第一篇就從單測的一個小點講起

背景

  作爲要禿頭的程序猿,我們每天要寫非常多的單測代碼,但是我們的單測目標更多時候是可以公開調用的Service層代碼或是 Controller層代碼,如果我們想測試Service層中我們悄悄寫的一些 private方法,就有難度了.
  如果一個項目是按一定規範開發的,測試代碼一般和業務源碼在不同包中,導致private方法無法在測試包中進行測試.這裏我們就講一個折中的辦法,來測試這些藏在角落裏的私有方法.

Start

  首先我們寫一個可測試的簡單用例

package com.example.demo.design.impl;

import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;

/**
 * ID生成器
 *
 * @author :Lingyun
 * @date :2020-02-17 17:46
 */
@Slf4j
public class RandomIdGenerator {

    private String generate() {
        return "我是private";
    }

}
改造:第一步

  我們知道私有方法在類外是肯定無法訪問的,這時候槓精可能要來了,反射可以啊.
  emmm,這種方案我們不考慮,爲了測試我們去寫一套反射實在是一件性價比很低的事情.既然private 方法不能在類外訪問,那我們只能對實現做一點小的改動,比如把private 換成 protected.

 protected String generate() {
        return "我是private";
 }
改造:第二步

  我們變更了方法的作用域,但是這樣操作是有風險的,通常private方法中我們並不會寫參數和業務的前置和後置的校驗,更多時候private方法都是代碼的封裝和抽象,我們修改了作用域,其他開發小夥伴在不知情的情況下貿然使用,可能會出各種問題.
  在這裏我們可以藉助Guava中提供的一個註解來標明private方法的這次作用域變更的用途@VisibleForTesting,這個註解並不會實際改變方法的作用域,只是起到註釋的作用,來告訴其他小夥伴調用此方法的風險

@VisibleForTesting
 protected String generate() {
        return "我是private";
 }
改造:第三步

  這時候如果你以爲這個方法就可以測試了,那你天真了,儘管generate()方法的作用域已經修改爲protected,但是因爲protected的只能包內調用的特性,我們在測試路徑寫的測試方法依然不能正常調用到改方法,比如這樣:



  接下來的一點改動就是本篇文章的精華所在了,下面是RandomIdGenerator類的包路徑

package com.example.demo.design.impl;

  然後我們在測試路徑下創建一個相同路徑下的測試類 比如這樣:



  是不是很神奇,明明測試類和RandomIdGenerator類不在相同的路徑下但是他們的 package 確是一樣的,這時候我們再看測試方法中的generate()調用也不再報錯了.
  我們執行以下測試方法,看是否能正常執行



  程序可以正常執行,並打印了日誌

End

  寫這篇的目的是幫助大家可以用較簡單和較低的成本來測試private方法,網上也有一些測試私有方法的文章,但是大多都是使用反射來實現的,這種方案每次都要去寫一套反射代碼,實用性並不高.至於方法的作用域的變更,只要標識明確清楚,對代碼的影響是可控的.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章