คุณสามารถเพิ่มข้อความที่กำหนดเองใน AssertJ assertThat ได้หรือไม่


93

เรามีชุดทดสอบที่ใช้การยืนยัน JUnit กับ Hamcrest matchers เป็นหลัก หนึ่งในทีมของเราเริ่มทดลองใช้AssertJและสร้างความประทับใจให้กับผู้คนด้วยไวยากรณ์ความยืดหยุ่นและความเปิดเผย มีคุณลักษณะหนึ่งที่ JUnit ให้ซึ่งฉันไม่พบสิ่งที่เทียบเท่าใน AssertJ นั่นคือการเพิ่มข้อความยืนยันความล้มเหลวแบบกำหนดเอง

เรามักจะเปรียบเทียบวัตถุที่ไม่ได้สร้างขึ้นเพื่อให้มนุษย์สามารถอ่านได้และจะมีรหัสหรือ UUID ที่ดูเหมือนสุ่มและเป็นไปไม่ได้ที่จะบอกว่าข้อมูลเหล่านั้นควรจะเป็นอย่างไร นี่เป็นสถานการณ์ที่หลีกเลี่ยงไม่ได้สำหรับ codebase ของเราน่าเศร้าที่ส่วนหนึ่งของวัตถุประสงค์ที่บรรลุคือการทำแผนที่ข้อมูลระหว่างบริการอื่น ๆ โดยไม่จำเป็นต้องเข้าใจว่ามันคืออะไร

ใน JUnit assertThatวิธีการจัดเตรียมเวอร์ชันที่มีString reasonพารามิเตอร์ก่อนMatcher<T>พารามิเตอร์ สิ่งนี้ทำให้การเพิ่มสตริงดีบักสั้น ๆ เป็นเรื่องเล็กน้อยซึ่งจะช่วยให้เกิดความกระจ่างเกี่ยวกับปัญหาเช่นการเปรียบเทียบควรมีความหมายกับมนุษย์อย่างไร

ในทางกลับกันAssertJ มีstatic assertThatวิธีการทั่วไปที่แตกต่างกันกว่าล้านล้านวิธีซึ่งส่งคืนรูปแบบของอินเทอร์เฟซ Assertหรือหนึ่งในคลาสที่นำไปใช้งานจำนวนมาก อินเทอร์เฟซนี้ไม่ได้จัดเตรียมวิธีมาตรฐานในการตั้งค่าข้อความที่กำหนดเองที่จะรวมกับความล้มเหลว

มีวิธีใดบ้างในการรับฟังก์ชันนี้จาก AssertJ API หรือหนึ่งในส่วนขยายโดยไม่ต้องสร้างคลาสการยืนยันที่กำหนดเองสำหรับทุกประเภทการยืนยันที่เราต้องการเพิ่มข้อความ

คำตอบ:


139

และในรูปแบบคลาสสิกฉันพบสิ่งที่ฉันกำลังมองหาในช่วงเวลาหนึ่งหลังจากโพสต์คำถาม หวังว่าสิ่งนี้จะช่วยให้คนต่อไปพบได้ง่ายขึ้นโดยไม่ต้องรู้ก่อนว่ามันเรียกว่าอะไร เมธอดมายากลคือชื่อย่อที่หลอกลวงasซึ่งเป็นส่วนหนึ่งของอินเทอร์เฟซอื่นที่AbstractAssertใช้: อธิบายได้ไม่ใช่อินเทอร์เฟซ Assert พื้นฐาน

public S as(String description, Object... args)

ตั้งค่าคำอธิบายของอ็อบเจ็กต์นี้ที่รองรับString.format(String, Object...)ไวยากรณ์
ตัวอย่าง:

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description with as() method or describedAs(), it supports String format args
  assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("[check Frodo's age] expected:<[33]> but was:<[50]>");
}

โดยที่สตริงที่ยกมาในบล็อก catch hasMessageคือสิ่งที่ปรากฏในบันทึกเอาต์พุตการทดสอบหน่วยของคุณหากการยืนยันล้มเหลว


ฉันพบสิ่งนี้โดยสังเกตเห็นตัวfailWithMessageช่วยในหน้าการยืนยันแบบกำหนดเองที่เชื่อมโยงในคำถาม JavaDocสำหรับวิธีการที่ชี้ให้เห็นว่ามันได้รับการคุ้มครองดังนั้นจึงไม่สามารถนำมาใช้โดยสายที่การตั้งค่าข้อความที่กำหนดเอง อย่างไรก็ตามมันไม่ได้กล่าวถึงasผู้ช่วยเหลือ:

นอกจากนี้วิธีการนี้ได้รับเกียรตินิยมชุดคำอธิบายใด ๆ กับหรือข้อผิดพลาดแทนที่กำหนดโดยผู้ใช้ที่มีas(String, Object...)overridingErrorMessage(String, Object...)

... และตัวช่วยoverridingErrorMessageซึ่งแทนที่expected: ... but was:...ข้อความAssertJ มาตรฐานทั้งหมดด้วยสตริงใหม่ที่ให้มา

หน้าแรกของ AssertJ ไม่ได้กล่าวถึงตัวช่วยใด ๆ จนกว่าจะถึงหน้าไฮไลต์คุณลักษณะซึ่งแสดงตัวอย่างของตัวasช่วยในส่วนSoft Assertionsแต่ไม่ได้อธิบายโดยตรงว่าทำอะไร


25

หากต้องการเพิ่มตัวเลือกอื่นให้กับคำตอบของ Patrick M:

แทนที่จะใช้Descriptable.asคุณยังสามารถใช้AbstractAssert.withFailMessage():

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description via withFailMessage(), supports String format args
  assertThat(frodo.getAge()).
    withFailMessage("Frodo's age is wrong: %s years, difference %s years",
      frodo.getAge(), frodo.getAge()-33).
    isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("Frodo's age is wrong: 50 years, difference 17 years");
}

ความแตกต่างในการใช้Descriptable.asคือช่วยให้คุณสามารถควบคุมข้อความที่กำหนดเองได้อย่างสมบูรณ์ - ไม่มีคำว่า "คาด" และ "แต่เดิม"

สิ่งนี้มีประโยชน์เมื่อค่าจริงที่กำลังทดสอบไม่มีประโยชน์สำหรับการนำเสนอ - วิธีนี้ช่วยให้คุณสามารถแสดงค่าอื่นที่อาจคำนวณได้แทนหรือไม่มีเลย


โปรดทราบว่าเช่นเดียวกับDescriptable.asคุณต้องโทรwithFailMessage() ก่อนการยืนยันจริง - มิฉะนั้นจะไม่ได้ผลเนื่องจากการยืนยันจะเริ่มขึ้นก่อน สิ่งนี้ระบุไว้ใน Javadoc


4
"คุณต้องโทรหา withFailMessage () ก่อนการยืนยันจริง"ขอบคุณสิ่งนี้ทำให้ฉันสะดุด ลำดับของการโทรwithFailMessage; ฉันชอบ AssertJ แต่มันแย่มาก
Abhijit Sarkar


0

ใช้as()เมธอดinbuilt ใน AssertJ ตัวอย่างเช่น:

 assertThat(myTest).as("The test microservice is not active").isEqualTo("active");
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.