我想定義一個抽象基類來定義通用可重用測試用例,我希望在測試各種API時一遍又一遍地執行這些測試用例。這個想法是定義一次測試,然後我可以從通用測試繼承來獲得測試定義,我所有的測試代碼都要執行測試執行的具體細節。這樣我就不會錯過好的測試用例,我不需要重新發明輪子,也不需要在數十個地方進行更改,當我想要另一個好的測試用例進行測試時。從調用堆棧中檢索最頂級註釋的函數
實質上,我正在做參數化測試,其中的參數是在基類中定義的。預期的結果也在基類中定義。但是,有時需要覆蓋預期的結果。例如,普通的字符串字段可能允許任何字符,而對象名字段可能(或者在我的情況下)限制哪些字符是合法的。例如,一個字符串字段允許「?」在該值中,名稱字段沒有。
我想弄清楚在基類中定義參數ONCE的乾淨方式,並且只定義了一次預期的結果,但是在上下文需要它的實現類中覆蓋它。
我的問題是,當你重寫一個方法時,你必須替換它的實現。你不能只替換它的一部分。我想在不覆蓋參數部分的情況下替換預期的結果。我也不認爲它是一種乾淨或理想的解決方案,可以將每個測試分解爲兩種方法,一種提供參數,另一種定義預期行爲。
我正在考慮的一個選項是使用註釋來定義預期結果。然後我可以重寫註釋,然後將實現委託給基類實現。只要基類使用註釋來決定如何表現,它就應該起作用。
例如:(僞代碼,而不是真正的Java)
abstract class foo {
@fubar(true)
void test1() { doSomething(param1) }
@fubar(true)
void test2() { doSomething(param2) }
@fubar(false)
void test3() { doSomething(param3) }
boolean isFubar(void) { ... } // generic annotation grabber
void doSomething(p) {
if (isFubar())
doThis(p)
else
doThat(p);
}
// abstract methods to be defined in the implementing class
void doThis(p);
void doThat(p);
}
class bar extends foo {
// change the expected result for test2 only
@fubar(false)
void test2() { super.test2(); }
// define how to execute the tests
void doThis(p) { ... }
void doThat(p) { ... }
}
class baz extends bar {
// only changes the semantics of test3, nothing else
@fubar(true)
void test3() { super.test3() }
}
考慮到這種層次,foo.test1()
,bar.test1()
和baz.test1()
都做同樣的事情。 foo.test2()
做一件事,而bar.test2()
和baz.test2()
做別的事情。同樣,foo.test3()
和bar.test3()
做了一件事,但baz.test3()
會有所不同。
我可以使用註釋來完成此行爲嗎?如果是這樣,isFubar
會是什麼樣子?我還沒有看到方法名稱未知的這種反射的例子。
作爲一個側面說明,如果沒有完成預期的行爲更清潔的方式,我很樂意聽到的是什麼。
聞起來像一個可能的XY問題。您可能希望查看AOP,或嘗試找到更多面向對象的方法。 – shmosel
請詳細說明*你想要完成什麼,而不是*如何*。按照你的代碼片斷,簡單地重寫'isFubar()'返回true或false,並完全丟棄註釋會更有意義。 – shmosel
此外,您提出的問題是作爲代碼請求發生的,這是在此處皺起眉頭。你有沒有試圖解決這個問題?你卡在哪裏? – shmosel