จะทดสอบได้อย่างไรว่าไม่มีข้อยกเว้นเกิดขึ้น?


238

ฉันรู้ว่าวิธีหนึ่งที่จะทำได้:

@Test
public void foo(){
   try{
      //execute code that you expect not to throw Exceptions.
   }
   catch(Exception e){
      fail("Should not have thrown any exception");
   }
}

มีวิธีใดที่สะอาดกว่าในการทำสิ่งนี้ (อาจใช้ Junit @Ruleหรือไม่?)


10
การทดสอบ JUnit จะตัดสินว่าล้มเหลวหากมีการส่งข้อยกเว้นอื่นนอกเหนือจากข้อยกเว้นที่คาดไว้ โดยปกติจะไม่มีข้อยกเว้นเกิดขึ้น
Raedwald

JUnit มีข้อแตกต่างระหว่างความล้มเหลวและข้อผิดพลาดหรือไม่? ครั้งแรกหมายถึงการทดสอบล้มเหลวครั้งที่สองหมายถึงสิ่งที่ไม่คาดคิดเกิดขึ้น
Vituel

คำตอบ:


198

คุณกำลังเข้าใกล้สิ่งนี้ในทางที่ผิด เพียงทดสอบการทำงานของคุณ: หากมีข้อผิดพลาดเกิดขึ้นการทดสอบจะล้มเหลวโดยอัตโนมัติ หากไม่มีข้อยกเว้นการทดสอบของคุณจะเปลี่ยนเป็นสีเขียว

ฉันสังเกตเห็นคำถามนี้ได้รับความสนใจเป็นครั้งคราวดังนั้นฉันจะขยายตัวเล็กน้อย

ความเป็นมาของการทดสอบหน่วย

เมื่อคุณทดสอบหน่วยสิ่งสำคัญคือการกำหนดสิ่งที่คุณควรพิจารณาในหน่วยงาน โดยทั่วไป: การแยก codebase ของคุณที่อาจมีหรือไม่มีหลายวิธีหรือคลาสที่แสดงถึงการทำงานเพียงส่วนเดียว

หรือตามที่กำหนดไว้ในศิลปะการทดสอบหน่วยรุ่นที่ 2 โดย Roy Osheroveหน้า 11:

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

สิ่งสำคัญที่ต้องตระหนักคือหน่วยงานหนึ่งมักจะไม่ใช่เพียงวิธีเดียว แต่ในระดับพื้นฐานมากเป็นวิธีหนึ่งและหลังจากนั้นจะถูกห่อหุ้มด้วยหน่วยงานอื่น

ป้อนคำอธิบายรูปภาพที่นี่

เป็นการดีที่คุณควรมีวิธีทดสอบสำหรับแต่ละหน่วยงานแยกต่างหากเพื่อให้คุณสามารถดูได้ทันทีว่ามีอะไรผิดปกติเกิดขึ้น ในตัวอย่างนี้มีวิธีการพื้นฐานที่เรียกว่าgetUserById()ซึ่งจะส่งคืนผู้ใช้และมีงานทั้งหมด 3 หน่วย

หน่วยแรกของการทำงานควรทดสอบว่าผู้ใช้ที่ถูกต้องจะถูกส่งกลับในกรณีของการป้อนข้อมูลที่ถูกต้องและไม่ถูกต้อง
ข้อยกเว้นใด ๆ ที่จะถูกโยนโดยแหล่งข้อมูลจะต้องได้รับการจัดการที่นี่: หากไม่มีผู้ใช้อยู่ควรมีการทดสอบที่แสดงให้เห็นว่ามีข้อยกเว้นโยนเมื่อผู้ใช้ไม่พบ ตัวอย่างนี้อาจเป็นสิ่งIllegalArgumentExceptionที่ติดอยู่กับ@Test(expected = IllegalArgumentException.class)คำอธิบายประกอบ

เมื่อคุณจัดการ usecases ทั้งหมดของคุณสำหรับหน่วยงานพื้นฐานนี้แล้วคุณจะเลื่อนระดับได้ ที่นี่คุณทำสิ่งเดียวกัน แต่คุณจะจัดการกับข้อยกเว้นที่มาจากระดับที่ต่ำกว่าระดับปัจจุบัน สิ่งนี้จะช่วยให้รหัสการทดสอบของคุณมีโครงสร้างที่ดีและช่วยให้คุณสามารถเรียกใช้งานสถาปัตยกรรมได้อย่างรวดเร็วเพื่อค้นหาสิ่งที่ผิดพลาดแทนที่จะต้องกระโดดไปทั่วสถานที่

การจัดการอินพุตที่ถูกต้องและผิดพลาดของการทดสอบ

ณ จุดนี้มันควรจะชัดเจนว่าเราจะจัดการกับข้อยกเว้นเหล่านี้ได้อย่างไร อินพุตมี 2 ประเภท: อินพุตที่ถูกต้องและอินพุตที่ผิดพลาด (อินพุตนั้นถูกต้องในความหมายที่เข้มงวด แต่ไม่ถูกต้อง)

เมื่อคุณทำงานกับอินพุตที่ถูกต้องคุณจะตั้งค่าความคาดหวังโดยนัยที่สิ่งใดก็ตามที่คุณทดสอบการเขียนจะทำงานได้

existingUserById_ShouldReturn_UserObjectเรียกวิธีดังกล่าวสามารถมีลักษณะเช่นนี้ หากวิธีนี้ล้มเหลว (เช่น: มีข้อผิดพลาดเกิดขึ้น) คุณจะรู้ว่ามีบางอย่างผิดปกติและคุณสามารถเริ่มขุดได้

ด้วยการเพิ่มการทดสอบอื่น ( nonExistingUserById_ShouldThrow_IllegalArgumentException) ที่ใช้อินพุตที่ผิดพลาดและคาดว่าจะมีข้อยกเว้นคุณสามารถดูว่าวิธีการของคุณทำในสิ่งที่ควรทำกับอินพุตที่ไม่ถูกต้องหรือไม่

TL; DR

คุณกำลังพยายามทำสองสิ่งในการทดสอบของคุณ: ตรวจสอบการป้อนที่ถูกต้องและผิดพลาด โดยการแบ่งออกเป็นสองวิธีที่แต่ละคนทำสิ่งหนึ่งคุณจะมีการทดสอบที่ชัดเจนมากขึ้นและภาพรวมที่ดีขึ้นของสิ่งที่ผิดพลาด

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


2
สิ่งคือฉันกำลังพยายาม TDD และหนึ่งในผู้ทำงานร่วมกันที่ฉันใช้คือโยนข้อยกเว้น ดังนั้นฉันจึงต้องทดสอบความจริงที่ว่าฉันกำลังใช้ข้อยกเว้นที่ผู้ร่วมทำงานมอบให้
Ankit Dhingra

6
คุณกำลังบอกว่าการทำงานของคุณขึ้นอยู่กับการจัดการข้อยกเว้นหรือไม่? นั่นเป็นกลิ่นรหัส: มีข้อยกเว้นที่ช่วยให้คุณจับปัญหาได้อย่างสวยงาม พวกมันไม่ได้ใช้สำหรับการควบคุมการไหล หากคุณต้องการทดสอบสถานการณ์ที่ควรมีการโยนข้อยกเว้นคุณควรใช้expectedคำอธิบายประกอบ หากคุณต้องการทดสอบสถานการณ์ที่รหัสของคุณล้มเหลวและคุณต้องการดูว่าข้อผิดพลาดได้รับการจัดการอย่างถูกต้องหรือไม่: ใช้expectedและอาจใช้การยืนยันเพื่อตรวจสอบว่าได้รับการแก้ไขแล้วหรือไม่
Jeroen Vannevel

สิ่งหนึ่งคือฉันไม่สามารถกู้คืนจากข้อยกเว้นที่เกิดขึ้นในผู้ทำงานร่วมกันและสิ่งที่ฉันทำก็แค่บันทึกปัญหาโดยใช้ log.debug ("ข้อความผิดพลาด") ดังนั้นจึงไม่มีผลข้างเคียงเกิดขึ้นเป็นส่วนหนึ่งของ catch block ที่ฉันสามารถยืนยันได้
Ankit Dhingra

5
@JeroenVannevel ใช้ได้อย่างสมบูรณ์แบบเพื่อทดสอบว่าสถานการณ์ข้อผิดพลาดที่ทำให้เกิดข้อยกเว้นที่จะถูกโยนนั้นได้รับการจัดการอย่างเหมาะสม
Thorbjørn Ravn Andersen

1
@dpk ใช่คุณทำได้ คุณเพิ่มthrows IllegalArgumentExceptionการทดสอบของคุณ สิ่งที่คุณต้องการในท้ายที่สุดคือการทดสอบของคุณเปลี่ยนเป็นสีแดงหากมีข้อยกเว้น ทีนี้ลองเดาดูสิ fail()คุณไม่จำเป็นต้องเขียน ดังที่ @Jeroen Vannevel เขียนว่า: "หากมีข้อผิดพลาดเกิดขึ้นการทดสอบจะล้มเหลวโดยอัตโนมัติ"
Amedee Van Gasse

132

ฉันสะดุดกับสิ่งนี้เนื่องจากกฎของ SonarQube "squid: S2699": "เพิ่มการยืนยันอย่างน้อยหนึ่งกรณีในการทดสอบนี้"

ฉันมีการทดสอบอย่างง่าย ๆ โดยมีเป้าหมายเพียงอย่างเดียวที่ต้องทำโดยไม่ต้องทำการยกเว้นข้อยกเว้น

พิจารณารหัสง่าย ๆ นี้:

public class Printer {

    public static void printLine(final String line) {
        System.out.println(line);
    }
}

คุณสามารถเพิ่มการยืนยันประเภทใดในการทดสอบวิธีนี้ แน่นอนว่าคุณสามารถลองดูได้ แต่นั่นเป็นเพียงโค้ดขยายตัว

การแก้ปัญหามาจาก JUnit เอง

ในกรณีที่ไม่มีข้อยกเว้นและคุณต้องการแสดงให้เห็นถึงพฤติกรรมนี้อย่างชัดเจนเพียงเพิ่มexpectedดังตัวอย่างต่อไปนี้:

@Test(expected = Test.None.class /* no exception expected */)
public void test_printLine() {
    Printer.printLine("line");
}

Test.None.class เป็นค่าเริ่มต้นสำหรับค่าที่คาดหวัง


30
ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุด คำตอบที่ได้รับการยอมรับนั้นดีมากและผู้เขียนนั้นก็ถูกต้องที่จะชี้ให้เห็นกลิ่นของรหัส อย่างไรก็ตามเขาไม่ได้ตอบคำถามเฉพาะ
HellishHeat

4
เป็นที่น่าสนใจที่จะทราบว่าค่าเริ่มต้นสำหรับคาดว่าจะไม่มีดังนั้นเพียงแค่คำอธิบายประกอบวิธีการกับ @Test จะทำ
oziomajnr


41

JUnit 5 (จูปิเตอร์) มีสามฟังก์ชันเพื่อตรวจสอบว่ามี / ไม่มีข้อยกเว้น:

assertAll​()

ยืนยันว่าสิ่งที่ให้มาทั้งหมดexecutables
  จะไม่ส่งข้อยกเว้น

assertDoesNotThrow​()

ยืนยันการดำเนินการของที่
  ให้มาด้วยexecutable/ supplier
ไม่เคยโยนชนิดใดมีข้อยกเว้น

  ฟังก์ชันนี้ใช้งานได้
  ตั้งแต่JUnit 5.2.0 (29 เมษายน 2018)

assertThrows​()

ยืนยันการดำเนินการของที่จัดว่าexecutable
โยนข้อยกเว้นของexpectedType
  และส่งกลับข้อยกเว้น

ตัวอย่าง

package test.mycompany.myapp.mymodule;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class MyClassTest {

    @Test
    void when_string_has_been_constructed_then_myFunction_does_not_throw() {
        String myString = "this string has been constructed";
        assertAll(() -> MyClass.myFunction(myString));
    }

    @Test
    void when_string_has_been_constructed_then_myFunction_does_not_throw__junit_v520() {
        String myString = "this string has been constructed";
        assertDoesNotThrow(() -> MyClass.myFunction(myString));
    }

    @Test
    void when_string_is_null_then_myFunction_throws_IllegalArgumentException() {
        String myString = null;
        assertThrows(
            IllegalArgumentException.class,
            () -> MyClass.myFunction(myString));
    }

}

1
นี่คือคำตอบที่ดีที่สุดตอนนี้ คำตอบอื่น ๆ กำลังพูดถึงรุ่นเก่าของ JUnit
Tejesh Raut

29

Java 8 ทำให้สิ่งนี้ง่ายขึ้นมากและ Kotlin / Scala เพิ่มขึ้นเป็นสองเท่า

เราสามารถเขียนคลาสอรรถประโยชน์เล็กน้อย

class MyAssertions{
  public static void assertDoesNotThrow(FailingRunnable action){
    try{
      action.run()
    }
    catch(Exception ex){
      throw new Error("expected action not to throw, but it did!", ex)
    }
  }
}

@FunctionalInterface interface FailingRunnable { void run() throws Exception }

จากนั้นรหัสของคุณจะกลายเป็น:

@Test
public void foo(){
  MyAssertions.assertDoesNotThrow(() -> {
    //execute code that you expect not to throw Exceptions.
  }
}

หากคุณไม่มีสิทธิ์เข้าถึง Java-8 ฉันจะใช้สิ่งอำนวยความสะดวก java แบบเก่าที่เจ็บปวด: บล็อกโค้ดแบบอาริบิทและความคิดเห็นง่าย ๆ

//setup
Component component = new Component();

//act
configure(component);

//assert 
/*assert does not throw*/{
  component.doSomething();
}

และสุดท้ายด้วย kotlin ภาษาที่ฉันเพิ่งตกหลุมรัก:

fun (() -> Any?).shouldNotThrow() 
    = try { invoke() } catch (ex : Exception){ throw Error("expected not to throw!", ex) }

@Test fun `when foo happens should not throw`(){

  //...

  { /*code that shouldn't throw*/ }.shouldNotThrow()
}

แม้ว่าจะมีเป็นจำนวนมากของห้องพักที่จะคุ้นเคยกับว่าวิธีที่คุณต้องการที่จะแสดงนี้ฉันถูกเสมอแฟนของยืนยันได้อย่างคล่องแคล่ว


เกี่ยวกับ

คุณกำลังเข้าใกล้สิ่งนี้ในทางที่ผิด เพียงทดสอบการทำงานของคุณ: หากมีข้อผิดพลาดเกิดขึ้นการทดสอบจะล้มเหลวโดยอัตโนมัติ หากไม่มีข้อยกเว้นการทดสอบของคุณจะเปลี่ยนเป็นสีเขียว

หลักการนี้ถูกต้อง แต่สรุปไม่ถูกต้อง

Java อนุญาตให้มีข้อยกเว้นสำหรับการไหลของการควบคุม นี้จะกระทำโดยรันไทม์ JRE ตัวเองใน APIs เช่นDouble.parseDoubleผ่านNumberFormatExceptionและผ่านPaths.getInvalidPathException

เมื่อคุณเขียนส่วนประกอบที่ตรวจสอบความถูกต้องของ Number Number Double.ParseDoubleอาจใช้ Regex หรือ parser ที่เขียนด้วยมือหรืออาจเป็นสิ่งที่ฝังกฏโดเมนอื่น ๆ ที่ จำกัด ช่วงของ double เป็นสิ่งที่เฉพาะเจาะจงวิธีที่ดีที่สุดในการทดสอบนี้ องค์ประกอบ? ฉันคิดว่าการทดสอบที่ชัดเจนจะยืนยันว่าเมื่อแยกสตริงผลลัพธ์ออกแล้วจะไม่มีข้อยกเว้นเกิดขึ้น ฉันจะเขียนการทดสอบโดยใช้ด้านบนassertDoesNotThrowหรือ/*comment*/{code}บล็อก สิ่งที่ต้องการ

@Test public void given_validator_accepts_string_result_should_be_interpretable_by_doubleParseDouble(){
  //setup
  String input = "12.34E+26" //a string double with domain significance

  //act
  boolean isValid = component.validate(input)

  //assert -- using the library 'assertJ', my personal favourite 
  assertThat(isValid).describedAs(input + " was considered valid by component").isTrue();
  assertDoesNotThrow(() -> Double.parseDouble(input));
}

ฉันขอแนะนำให้คุณกำหนดพารามิเตอร์การทดสอบนี้inputโดยใช้TheoriesหรือParameterizedเพื่อให้คุณได้ง่ายขึ้นสามารถกลับมาใช้การทดสอบนี้สำหรับปัจจัยการผลิตอื่น ๆ อีกทางเลือกหนึ่งถ้าคุณต้องการแปลกใหม่คุณสามารถใช้เครื่องมือทดสอบรุ่น (และสิ่งนี้ ) TestNG ได้รับการสนับสนุนที่ดีกว่าสำหรับการทดสอบแบบกำหนดพารามิเตอร์

สิ่งที่ฉันพบไม่พอใจโดยเฉพาะอย่างยิ่งเป็นคำแนะนำในการใช้@Test(expectedException=IllegalArgumentException.class), ข้อยกเว้นนี้เป็นอันตรายในวงกว้าง หากรหัสของคุณเปลี่ยนแปลงเช่นนั้นองค์ประกอบภายใต้ตัวสร้างของการทดสอบมีif(constructorArgument <= 0) throw IllegalArgumentException()และการทดสอบของคุณจัดหา 0 สำหรับอาร์กิวเมนต์นั้นเพราะสะดวก - และนี่เป็นเรื่องธรรมดามากเพราะข้อมูลทดสอบที่สร้างดีนั้นเป็นปัญหาที่ยากอย่างน่าประหลาดใจ - จากนั้นการทดสอบของคุณ จะเป็นแถบสีเขียวแม้ว่าจะไม่ได้ทดสอบอะไรเลย การทดสอบดังกล่าวแย่กว่าไร้ประโยชน์


2
(เกี่ยวกับการใช้งานของข้อยกเว้นที่คาดไว้) ตั้งแต่ JUnit 4.13 คุณสามารถใช้Assert.assertThrowsเพื่อตรวจสอบว่าบางรหัสมีข้อยกเว้น
MageWind

22

หากคุณโชคไม่ดีที่พบข้อผิดพลาดทั้งหมดในรหัสของคุณ คุณสามารถทำอย่างโง่เขลา

class DumpTest {
    Exception ex;
    @Test
    public void testWhatEver() {
        try {
            thisShouldThrowError();
        } catch (Exception e) {
            ex = e;
        }
        assertEquals(null,ex);
    }
}

1
เพียงข้อเสนอแนะเล็ก ๆException exควรอยู่= null;ก่อนที่คุณจะสามารถทดสอบได้
Denees

4
นี่ไม่ใช่ทางออกที่ดี หากวิธีการที่ไม่ควรทิ้งข้อยกเว้นเกิดขึ้นคุณจะไม่ได้รับข้อความแสดงข้อผิดพลาดที่เป็นประโยชน์ เพียงเรียกวิธีการที่ไม่ควรทิ้งข้อยกเว้นและทดสอบค่าตอบแทน (หรือผลข้างเคียงเช่นบันทึกข้อยกเว้น) หากในภายหลังมีข้อผิดพลาดโดยไม่คาดคิดการทดสอบจะล้มเหลว
NamshubWriter

3
หรือเพียงแค่ใส่ Assert.fail () ลงใน IMO ที่ง่ายและสวยกว่าเดิม
isaac.hazan

ใช่ฉันเห็นด้วยกับคุณ. อีกวิธีหนึ่งคือเพิ่มคำอธิบายประกอบที่ด้านบนของวิธีการ @Test (คาดว่า = InvalidRequestException.class)
Ben Tennyson

ของคุณผิดพลาดการสะกดเป็นความสับสน: thisShouldThroughError -> thisShouldThrowError
Oscar Bravo


7

แม้ว่าโพสต์นี้จะมีอายุ 6 ปีแล้ว แต่มีการเปลี่ยนแปลงมากมายในโลก Junit ด้วย Junit5 คุณสามารถใช้งานได้แล้ว

org.junit.jupiter.api.Assertions.assertDoesNotThrow()

Ex:

public void thisMethodDoesNotThrowException(){
   System.out.println("Hello There");
}

@Test
public void test_thisMethodDoesNotThrowException(){
  org.junit.jupiter.api.Assertions.assertDoesNotThrow(
      ()-> thisMethodDoesNotThrowException()
    );
}

หวังว่ามันจะช่วยให้ผู้ที่ใช้ Junit5 รุ่นใหม่


ฉันหวังว่าจะมีวิธีระบุคลาสข้อยกเว้นที่เป็นรูปธรรมที่นี่ ฉันต้องทำภายในนี้'sAwaitility untilAsserted(ThrowingRunnable assertion)ขณะนี้ระบบภายใต้การทดสอบกำลังขว้างข้อยกเว้นเฉพาะใน ThrowingRunnable ที่ฉันให้ แต่ฉันต้องการให้เวลาสักครู่จนกว่าจะหยุดทำ อย่างไรก็ตามถ้ามันจะมีข้อยกเว้นที่แตกต่างกันฉันต้องการทดสอบล้มเหลวทันที
Ubeogesh

1

หากคุณต้องการทดสอบว่าเป้าหมายการทดสอบของคุณใช้ข้อยกเว้นหรือไม่ เพียงแค่ปล่อยให้การทดสอบเป็น (จำลองผู้ทำงานร่วมกันโดยใช้ jMock2):

@Test
public void consumesAndLogsExceptions() throws Exception {

    context.checking(new Expectations() {
        {
            oneOf(collaborator).doSth();
            will(throwException(new NullPointerException()));
        }
    });

    target.doSth();
 }

การทดสอบจะผ่านหากเป้าหมายของคุณใช้ข้อยกเว้นเกิดขึ้นมิฉะนั้นการทดสอบจะล้มเหลว

หากคุณต้องการทดสอบตรรกะการใช้ข้อยกเว้นของคุณสิ่งต่างๆจะซับซ้อนมากขึ้น ฉันขอแนะนำให้มอบหมายการบริโภคให้ผู้ทำงานร่วมกันซึ่งอาจถูกล้อเลียน ดังนั้นการทดสอบอาจเป็น:

@Test
public void consumesAndLogsExceptions() throws Exception {
    Exception e = new NullPointerException();
    context.checking(new Expectations() {
        {
            allowing(collaborator).doSth();
            will(throwException(e));

            oneOf(consumer).consume(e);
        }
    });

    target.doSth();
 }

แต่บางครั้งมันถูกออกแบบมามากเกินไปหากคุณต้องการเข้าสู่ระบบ ในกรณีนี้บทความนี้ ( http://java.dzone.com/articles/monitoring-declarative-transac , http://blog.novoj.net/2008/09/20/testing-aspect-pointcuts-is-there -an-easy-way / ) อาจช่วยได้หากคุณยืนยัน tdd ในกรณีนี้


1

ใช้assertNull (... )

@Test
public void foo() {
    try {
        //execute code that you expect not to throw Exceptions.
    } catch (Exception e){
        assertNull(e);
    }
}

6
ฉันจะบอกว่านี่เป็นสิ่งที่ทำให้เข้าใจผิด บล็อก catch ไม่ถูกเข้าถึงดังนั้นจึงassertNullไม่เคยถูกดำเนินการเช่นกัน อย่างไรก็ตามผู้อ่านที่รวดเร็วจะได้รับความประทับใจว่าการยืนยันนั้นทำขึ้นเพื่อยืนยันว่าเป็นคดีที่ไม่ได้เกิดขึ้นจริง ในคำอื่น ๆ : ถ้าจับบล็อกจะถึงข้อยกเว้นอยู่เสมอไม่ใช่ null - failมันสามารถจึงถูกแทนที่ด้วยง่าย
Andreas

ทำให้เข้าใจผิดแน่นอน ..... แต่เดี๋ยวก่อน ... โอ้ฉันเข้าใจแล้ว ... assertNull(e)จะรายงานการทดสอบล้มเหลวตามที่ระบุไว้eไม่สามารถnullอยู่ในcatchบล็อกได้ ... ไมค์นี่เป็นเพียงการเขียนโปรแกรมแปลก ๆ : - / .. ใช่อย่างน้อยก็ใช้fail()อย่าง Andreas พูดว่า
Julien

1

คุณสามารถคาดหวังได้ว่าข้อยกเว้นจะไม่ถูกส่งออกไปโดยการสร้างกฎ

@Rule
public ExpectedException expectedException = ExpectedException.none();

ExpectedExceptions ใช้เพื่อยืนยันข้อยกเว้นที่ส่งออกมา รหัสที่คุณให้ไว้เป็นเพียงการเริ่มต้นกฎเพื่อให้คุณสามารถเพิ่มความต้องการของคุณสำหรับการยืนยัน รหัสนี้เองไม่ได้เพิ่มค่าใด ๆ เลย javadoc ยังระบุสิ่งนี้: "/ ** * คืนค่า {@linkplain TestRule rule} ที่คาดว่าจะไม่มีข้อยกเว้น * ถูกโยน (เหมือนกับพฤติกรรมที่ไม่มีกฎนี้) * /" ดังนั้นมันจะมีผลลัพธ์แบบเดียวกับที่ไม่มี .
Pim Hazebroek

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

ฉันอยากรู้ว่าคุณจะยืนยันด้วยข้อยกเว้นที่คาดหวังได้อย่างไร และใช่ถ้าความต้องการเปลี่ยนไปและคุณไม่มีการทดสอบกรณีขอบเฉพาะที่คุณเมา ;-) ครอบคลุมทุกกรณีมุม
Pim Hazebroek

คุณหมายถึงอะไร คุณไม่ยืนยันมันคุณคาดหวัง ในกรณีนี้คุณคาดว่าจะไม่มีข้อยกเว้น ไม่แน่ใจว่าคุณกำลังทำอะไรอยู่
LazerBanana

0

นี่อาจไม่ใช่วิธีที่ดีที่สุด แต่แน่นอนว่าทำให้แน่ใจว่าไม่มีการยกเว้นจากการบล็อกโค้ดที่กำลังทดสอบ

import org.assertj.core.api.Assertions;
import org.junit.Test;

public class AssertionExample {

    @Test
    public void testNoException(){
        assertNoException();
    }    

    private void assertException(){
        Assertions.assertThatThrownBy(this::doNotThrowException).isInstanceOf(Exception.class);
    }

    private void assertNoException(){
        Assertions.assertThatThrownBy(() -> assertException()).isInstanceOf(AssertionError.class);
    }

    private void doNotThrowException(){
        //This method will never throw exception
    }
}

0

คุณสามารถทำได้โดยใช้ @Rule แล้วเรียกวิธีการ reportMissingExceptionWithMessage ดังที่แสดงด้านล่าง: นี่คือรหัสสกาล่า

ป้อนคำอธิบายรูปภาพที่นี่


1
private val? ภาษานี้คืออะไร? ไม่ชัดเจน Java; p และโปรดอย่าให้รหัสเป็นภาพหน้าจอไม่ยินดี
Andremoniy

ฉันเห็นคุณได้กล่าวถึงมันคือ Scala แต่การบอกว่าสามารถทำได้อย่างง่ายดายใน Java ไม่ใช่ข้อโต้แย้งที่แข็งแกร่งฉันขอโทษ
Andremoniy

ฉันลบส่วนที่รบกวนคุณ ฉันจะพยายามแทนที่ภาพด้วย ยังไม่ได้คิดวิธีเพิ่มรหัสเลย ..
Crenguta S

-1

การทดสอบต่อไปนี้ล้มเหลวสำหรับข้อยกเว้นทั้งหมดทำเครื่องหมายหรือไม่เลือก:

@Test
public void testMyCode() {

    try {
        runMyTestCode();
    } catch (Throwable t) {
        throw new Error("fail!");
    }
}

-1

คุณสามารถสร้างการยืนยันของคุณเองใด ๆ ขึ้นอยู่กับการยืนยันจาก junit:

static void assertDoesNotThrow(Executable executable) {
    assertDoesNotThrow(executable, "must not throw");
}
static void assertDoesNotThrow(Executable executable, String message) {
    try {
        executable.execute();
    } catch (Throwable err) {
        fail(message);
    }
}

และทดสอบ:

//the following will succeed
assertDoesNotThrow(()->methodMustNotThrow(1));
assertDoesNotThrow(()->methodMustNotThrow(1), "fail with specific message: facepalm");
//the following will fail
assertDoesNotThrow(()->methodMustNotThrow(2));
assertDoesNotThrow(()-> {throw new Exception("Hello world");}, "Fail: must not trow");

โดยทั่วไปการพูดมีความเป็นไปได้ที่จะล้มเหลวทันที ("bla bla bla") การทดสอบในทุกสถานการณ์ในทุกสถานที่ที่เหมาะสม ตัวอย่างเช่นใช้ในบล็อกลอง / จับเพื่อล้มเหลวหากมีอะไรโยนในกรณีทดสอบ:

try{methodMustNotThrow(1);}catch(Throwable e){fail("must not throw");}
//or
try{methodMustNotThrow(1);}catch(Throwable e){Assertions.fail("must not throw");}

นี่คือตัวอย่างของวิธีที่เราทดสอบสมมติว่าเรามีวิธีการดังกล่าวที่จะต้องไม่ล้มเหลวภายใต้สถานการณ์ที่เฉพาะเจาะจง แต่สามารถล้มเหลวได้:

void methodMustNotThrow(int x) throws Exception{
    if (x == 1) return;
    throw new Exception();
}

วิธีการดังกล่าวเป็นตัวอย่างง่ายๆ แต่สิ่งนี้ใช้ได้กับสถานการณ์ที่ซับซ้อนซึ่งความล้มเหลวไม่ชัดเจนนัก มีการนำเข้า:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import static org.junit.jupiter.api.Assertions.*;

มีตัวเลือกที่ค่อนข้างดีกว่าในการตรวจสอบว่ายังไม่มีการยืนยันซึ่งไม่เกี่ยวข้องกับการสร้างรหัสที่กำหนดเอง @Rule เป็นหนึ่งในนั้น
Vargan

@Vargan ฉันได้ชี้ให้เห็นวิธีการสร้างการยืนยันของคุณเองในแบบที่ออกแบบโดย JUnit โดยเฉพาะอย่างยิ่งเพื่อวัตถุประสงค์ในการสร้างการยืนยันของคุณเอง JUnit จัดเตรียมโดยการออกแบบโดยเฉพาะอย่างยิ่งสำหรับวัตถุประสงค์นั้นเพื่อสร้างกฎของคุณเองให้ขยายลักษณะการทำงานของ JUnit ด้วยการยืนยันที่ยังไม่ได้ใช้งาน เนื่องจากไม่ใช่ทุกสิ่งที่ถูกนำมาใช้ในโลกนี้การยืนยันเหล่านี้ทำงานเหมือนกันกับการยืนยัน JUnit ทำงานในแง่ของการผ่านหรือล้มเหลวรวมถึงการรายงานความล้มเหลว
armagedescu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.