ฉันตั้งค่าชั้นเรียนด้วยการทดสอบสองสามครั้งและแทนที่จะใช้@Before
ฉันอยากจะมีวิธีการตั้งค่าที่ดำเนินการเพียงครั้งเดียวก่อนการทดสอบทั้งหมด เป็นไปได้กับ Junit 4.8 หรือไม่?
ฉันตั้งค่าชั้นเรียนด้วยการทดสอบสองสามครั้งและแทนที่จะใช้@Before
ฉันอยากจะมีวิธีการตั้งค่าที่ดำเนินการเพียงครั้งเดียวก่อนการทดสอบทั้งหมด เป็นไปได้กับ Junit 4.8 หรือไม่?
คำตอบ:
แม้ว่าฉันจะเห็นด้วยกับ @assylias ว่าการใช้@BeforeClass
เป็นวิธีแก้ปัญหาแบบคลาสสิก แต่ก็ไม่สะดวกเสมอไป วิธีการที่ใส่คำอธิบายประกอบ@BeforeClass
ต้องเป็นแบบคงที่ ไม่สะดวกสำหรับการทดสอบบางอย่างที่จำเป็นต้องมีกรณีทดสอบ ตัวอย่างเช่นการทดสอบตามสปริงที่ใช้@Autowired
เพื่อทำงานกับบริการที่กำหนดไว้ในบริบทฤดูใบไม้ผลิ
ในกรณีนี้ฉันใช้setUp()
วิธีการปกติที่มี@Before
คำอธิบายประกอบและจัดการแฟล็กstatic
(!) ที่ กำหนดเองboolean
:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
เมธอดอยู่ในซูเปอร์คลาส - ได้โพสต์คำตอบด้านล่างเพื่อพยายามแก้ไขปัญหานี้
คุณสามารถใช้บันทึกย่อ :BeforeClass
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
แทนการโทร getClass () ของคุณได้? นี่คือ Java จริง: String.class.getName()
.
ตอนนี้ JUnit 5 มีคำอธิบายประกอบ @BeforeAll:
แสดงว่าเมธอดคำอธิบายประกอบควรถูกเรียกใช้ก่อนเมธอด @Test ทั้งหมดในคลาสปัจจุบันหรือลำดับชั้นคลาส คล้ายกับ @BeforeClass ของ JUnit 4 วิธีการดังกล่าวต้องเป็นแบบคงที่
คำอธิบายประกอบวงจรชีวิตของ JUnit 5 ดูเหมือนจะถูกต้องในที่สุด! คุณสามารถเดาได้ว่ามีคำอธิบายประกอบใดบ้างโดยไม่ต้องดู (เช่น @BeforeEach @AfterAll)
@BeforeClass
static
โซลูชันของ IMO @ AlexR นั้นดีกว่า
เมื่อsetUp()
ใดที่อยู่ในซูเปอร์คลาสของคลาสทดสอบ (เช่นAbstractTestBase
ด้านล่าง) คำตอบที่ยอมรับสามารถแก้ไขได้ดังนี้:
public abstract class AbstractTestBase {
private static Class<? extends AbstractTestBase> testClass;
.....
public void setUp() {
if (this.getClass().equals(testClass)) {
return;
}
// do the setup - once per concrete test class
.....
testClass = this.getClass();
}
}
สิ่งนี้น่าจะใช้ได้กับวิธีการเดียวที่ไม่คงที่setUp()
แต่ฉันไม่สามารถสร้างสิ่งที่เทียบเท่าได้tearDown()
โดยไม่หลงเข้าไปในโลกแห่งการสะท้อนที่ซับซ้อน ... ค่าหัวชี้ให้ทุกคนที่ทำได้!
แก้ไข: ฉันเพิ่งค้นพบในขณะที่การดีบักว่าคลาสนั้นถูกสร้างอินสแตนซ์ก่อนการทดสอบทุกครั้งด้วย ฉันเดาว่าคำอธิบายประกอบ @BeforeClass ดีที่สุดที่นี่
คุณสามารถตั้งค่าบนคอนสตรัคเตอร์ได้เช่นกันคลาสทดสอบเป็นคลาสหลังจากทั้งหมด ฉันไม่แน่ใจว่าเป็นการปฏิบัติที่ไม่ดีหรือไม่เพราะวิธีอื่น ๆ เกือบทั้งหมดมีคำอธิบายประกอบ แต่ก็ใช้ได้ผล คุณสามารถสร้างตัวสร้างเช่นนั้น:
public UT () {
// initialize once here
}
@Test
// Some test here...
ctor จะถูกเรียกก่อนการทดสอบเนื่องจากไม่คงที่
ลองใช้วิธีนี้: https://stackoverflow.com/a/46274919/907576 :
ด้วย@BeforeAllMethods
/ @AfterAllMethods
คำอธิบายประกอบคุณสามารถเรียกใช้เมธอดใดก็ได้ในคลาสทดสอบในบริบทอินสแตนซ์ซึ่งมีค่าที่แทรกทั้งหมด
วิธีแก้สกปรกของฉันคือ:
public class TestCaseExtended extends TestCase {
private boolean isInitialized = false;
private int serId;
@Override
public void setUp() throws Exception {
super.setUp();
if(!isInitialized) {
loadSaveNewSerId();
emptyTestResultsDirectory();
isInitialized = true;
}
}
...
}
ฉันใช้มันเป็นฐานสำหรับ testCases ทั้งหมดของฉัน
หากคุณไม่ต้องการบังคับให้ประกาศตัวแปรที่ตั้งค่าและตรวจสอบในการทดสอบย่อยแต่ละครั้งการเพิ่มสิ่งนี้ใน SuperTest สามารถทำได้
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
@Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
ฉันแก้ไขปัญหานี้ดังนี้:
เพิ่มลงในคลาสBase abstract ของคุณ(ฉันหมายถึงคลาสนามธรรมที่คุณเริ่มต้นไดรเวอร์ของคุณในเมธอด setUpDriver () ) ส่วนนี้ของโค้ด:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
และตอนนี้ถ้าคลาสทดสอบของคุณจะขยายจากคลาสนามธรรมพื้นฐาน -> setUpDriver ()วิธีการจะถูกดำเนินการก่อน @Test แรกเพียงหนึ่งครั้งต่อการรัน
ใช้เมธอด @PostConstruct ของ Spring เพื่อเริ่มต้นทำงานทั้งหมดและวิธีนี้จะทำงานก่อนที่ @Test จะดำเนินการ