JUnit 4 පරීක්ෂණ වලදී කිසියම් ව්‍යතිරේකයක් දමා ඇති බව ඔබ ප්‍රකාශ කරන්නේ කෙසේද?


2014

සමහර කේතයන් ව්‍යතිරේකයක් විසි කරන බව පරීක්ෂා කිරීමට මට JUnit4 මුග්ධ ලෙස භාවිතා කළ හැක්කේ කෙසේද?

මට නිසැකවම මේ වගේ දෙයක් කළ හැකි අතර:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  boolean thrown = false;

  try {
    foo.doStuff();
  } catch (IndexOutOfBoundsException e) {
    thrown = true;
  }

  assertTrue(thrown);
}

මට මතකයි මේ ආකාරයේ තත්වයන් සඳහා විවරණයක් හෝ ඇසර්ට්.සික්ස් හෝ ජුනිට්ගේ ආත්මයට වඩා බෙහෙවින් අඩු හාස්‍යජනක දෙයක් තිබේ.


21
වෙනත් ඕනෑම ප්‍රවේශයක ගැටලුව නමුත් මෙය ව්‍යතිරේකය විසි කළ පසු ඔවුන් නිරන්තරයෙන් පරීක්ෂණය අවසන් කිරීමයි. අනෙක් අතට, org.mockito.Mockito.verifyව්‍යතිරේකය විසි කිරීමට පෙර යම් යම් දේවල් සිදුවී ඇත්දැයි (නිවැරදි පරාමිතීන් සමඟ ල ger ු-සටහන් සේවාවක් කැඳවනු ලැබීය) සහතික කිරීම සඳහා විවිධ පරාමිතීන් සමඟ ඇමතීමට මට බොහෝ විට අවශ්‍යය .
ZeroOne


6
Ero ZeroOne - ඒ සඳහා මට වෙනස් පරීක්ෂණ දෙකක් තිබේ - එකක් ව්‍යතිරේකය සඳහා සහ එකක් ඔබේ සමච්චලය සමඟ අන්තර්ක්‍රියා සත්‍යාපනය කිරීම.
tddmonkey

JUnit 5 සමඟ මෙය කිරීමට ක්‍රමයක් තිබේ, මම මගේ පිළිතුර පහත යාවත්කාලීන කර ඇත.
දිලිනි රාජපක්ෂ

Answers:


2370

එය JUnit අනුවාදය සහ ඔබ භාවිතා කරන පුස්තකාල මත රඳා පවතී.

සඳහා මුල් පිළිතුර JUnit <= 4.12වූයේ:

@Test(expected = IndexOutOfBoundsException.class)
public void testIndexOutOfBoundsException() {

    ArrayList emptyList = new ArrayList();
    Object o = emptyList.get(0);

}

පිළිතුර https://stackoverflow.com/a/31826781/2986984 ට JUnit <= 4.12 සඳහා තවත් විකල්ප ඇත.

යොමුව:


66
ඔබේ කේතයේ කොතැනක හෝ පමණක් ව්‍යතිරේකයක් අපේක්ෂා කරන්නේ නම් මෙම කේත කොටස ක්‍රියා නොකරනු ඇත.
ඔහ් චින් බූන්

4
kskaffman මෙය org.junit.experimental.theories සමඟ ක්‍රියා නොකරනු ඇත. org.junit.experimental.theories විසින් මෙහෙයවනු ලබන න්‍යාය
Artem Oboturov

75
රෝයි ඔෂෙරෝව් විසින් මෙම ආකාරයේ ව්‍යතිරේක පරීක්ෂාව අධෛර්යමත් කරයි , මන්ද ව්‍යතිරේකය පරීක්ෂණය තුළ ඕනෑම තැනක තිබිය හැකි අතර පරීක්ෂණයට භාජනය වන ඒකකය තුළ පමණක් නොවේ.
කෙවින් විට්ටෙක්

21
Iv Kiview / Roy Osherove සමඟ මම එකඟ නොවෙමි. මගේ මතය අනුව, පරීක්ෂණ විය යුත්තේ හැසිරීම සඳහා මිස ක්‍රියාත්මක කිරීම සඳහා නොවේ. නිශ්චිත ක්‍රමයක් මඟින් දෝෂයක් ඇතිවිය හැකි බව පරීක්ෂා කිරීමෙන්, ඔබ ඔබේ පරීක්ෂණ සෘජුවම ක්‍රියාත්මක කිරීමට සම්බන්ධ කරයි. ඉහත පෙන්වා ඇති ක්‍රමවේදය පරීක්ෂා කිරීම වඩා වටිනා පරීක්ෂණයක් සපයන බව මම තර්ක කරමි. මම එකතු කරන අවවාදය නම්, මේ අවස්ථාවේ දී මම අභිරුචි ව්‍යතිරේකයක් සඳහා පරීක්‍ෂා කරමි, එවිට මට සැබවින්ම අවශ්‍ය ව්‍යතිරේකය ලැබෙන බව මම දනිමි.
nickbdyer

6
එසේ නොවේ. මට පන්තියේ හැසිරීම පරීක්ෂා කිරීමට අවශ්‍යයි. වැදගත් දෙය නම්, එහි නොමැති දෙයක් ලබා ගැනීමට මම උත්සාහ කළහොත්, මට ව්‍යතිරේකයක් ලැබෙනු ඇත. දත්ත ව්‍යුහය ArrayListඊට ප්‍රතිචාර දැක්වීම get()අදාල නොවේ. මම අනාගතයේදී ප්‍රාථමික අරාවකට යාමට තෝරා ගත්තා නම්, එවිට මට මෙම පරීක්ෂණ ක්‍රියාත්මක කිරීම වෙනස් කිරීමට සිදුවේ. දත්ත ව්‍යුහය සැඟවිය යුතු අතර එමඟින් පරීක්ෂණයට පන්තියේ හැසිරීම කෙරෙහි අවධානය යොමු කළ හැකිය .
nickbdyer

1321

සංස්කරණය කරන්න: දැන් JUnit 5 සහ JUnit 4.13 නිකුත් කර ඇති බැවින් හොඳම විකල්පය වනුයේ Assertions.assertThrows() (JUnit 5 සඳහා) සහ Assert.assertThrows()(JUnit 4.13 සඳහා) භාවිතා කිරීමයි. විස්තර සඳහා මගේ අනෙක් පිළිතුර බලන්න.

ඔබ JUnit 5 වෙත සංක්‍රමණය වී නොමැති නමුත් JUnit 4.7 භාවිතා කළ හැකි නම්, ඔබට ExpectedExceptionරීතිය භාවිතා කළ හැකිය :

public class FooTest {
  @Rule
  public final ExpectedException exception = ExpectedException.none();

  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    exception.expect(IndexOutOfBoundsException.class);
    foo.doStuff();
  }
}

මෙය වඩා හොඳ වන්නේ මීට පෙර විසි @Test(expected=IndexOutOfBoundsException.class)කළහොත් පරීක්ෂණය අසමත් වන බැවිනිIndexOutOfBoundsExceptionfoo.doStuff()

විස්තර සඳහා මෙම ලිපිය බලන්න


14
@ ස්කාෆ්මන් - මම මෙය නිවැරදිව වටහාගෙන ඇත්නම්, එය ව්‍යතිරේකය ලෙස පෙනේ.
බකාර්

5
අප විසි කිරීමට අපේක්ෂා කරන ව්‍යතිරේකය පරීක්ෂා කළ ව්‍යතිරේකයක් නම්, අපි විසි කිරීම් එකතු කළ යුතුද? නැතහොත් වෙනත් ආකාරයකින් මෙම තත්වය පරීක්ෂා කළ යුතුද?
මොහොමඩ් ජෆාර් මාෂාඩි

5
ArtMartinTrummer ව්‍යතිරේකය විසි කර ක්‍රමය පිටවී ඇති බැවින් foo.doStuff () පසු කිසිදු කේතයක් ක්‍රියාත්මක නොවිය යුතුය. අපේක්ෂිත ව්‍යතිරේකයකින් පසු කේතයක් තිබීම (අවසාන වශයෙන් සම්පත් වසා දැමීම හැර) කෙසේ හෝ උදව් කළ නොහැකි බැවින් ව්‍යතිරේකය විසි කළ හොත් එය කිසි විටෙකත් ක්‍රියාත්මක නොකළ යුතුය.
ජේසන් තොම්සන්

9
මෙය හොඳම ප්‍රවේශයයි. ස්කැෆ්මන්ගේ විසඳුමට සාපේක්ෂව මෙහි වාසි දෙකක් තිබේ. පළමුවෙන්ම, ExpectedExceptionපංතියට ව්‍යතිරේකයේ පණිවිඩය ගැලපීමේ ක්‍රම තිබේ, නැතහොත් ව්‍යතිරේකයේ පන්තිය මත රඳා පවතින ඔබේම මැච් එකක් ලිවීම. දෙවනුව, ඔබ ව්‍යතිරේකය විසි කිරීමට අපේක්ෂා කරන කේත රේඛාවට පෙර ඔබේ අපේක්ෂාව සැකසිය හැකිය - එයින් අදහස් වන්නේ වැරදි කේත රේඛාවක් ව්‍යතිරේකය විසි කළහොත් ඔබේ පරීක්ෂණය අසාර්ථක වනු ඇති බවයි; ස්කෆ්මන්ගේ විසඳුම සමඟ එය කිරීමට ක්‍රමයක් නොමැත.
ඩාවුඩ් ඉබ්න් කරීම්

5
JMJafarMash ඔබ විසි කිරීමට බලාපොරොත්තු වන ව්‍යතිරේකය පරීක්ෂා කර ඇත්නම්, ඔබ එම ව්‍යතිරේකය පරීක්ෂණ ක්‍රමයේ විසි කිරීමේ වගන්තියට එකතු කරනු ඇත. විශේෂිත පරීක්ෂණ අවස්ථාවකදී ව්‍යතිරේකය අවුලුවනු නොලැබුවද, පරීක්ෂා කරන ලද ව්‍යතිරේකයක් විසි කරන බව ප්‍රකාශ කරන ක්‍රමවේදයක් ඔබ පරීක්‍ෂා කරන ඕනෑම වේලාවක ඔබත් එසේ කරයි.
නම්ෂුබ් රයිටර්

474

අපේක්ෂිත ව්‍යතිරේකය භාවිතා කිරීමට ප්‍රවේශම් වන්න, මන්ද එය තහවුරු කරන්නේ ක්‍රමවේදය එම ව්‍යතිරේකය විසි කළේ මිස නිශ්චිත කේත රේඛාවක් නොවන බවයි පරීක්ෂණයේ .

පරාමිති වලංගුභාවය පරීක්ෂා කිරීම සඳහා මම මෙය භාවිතා කිරීමට නැඹුරු වෙමි, මන්ද එවැනි ක්‍රම සාමාන්‍යයෙන් ඉතා සරල ය, නමුත් වඩා සංකීර්ණ පරීක්ෂණ සමඟ වඩා හොඳ සේවය කළ හැකිය:

try {
    methodThatShouldThrow();
    fail( "My method didn't throw when I expected it to" );
} catch (MyException expectedException) {
}

විනිශ්චය යොදන්න.


95
සමහර විට මම පරණ පාසලක් නමුත් මම තවමත් මේකට කැමතියි. ව්‍යතිරේකය පරික්ෂා කිරීමට එය මට ස්ථානයක් ලබා දෙයි: සමහර විට මට ඇතැම් අගයන් සඳහා ගැණුම්කරුවන් සමඟ ව්‍යතිරේක තිබේ, නැතහොත් මම පණිවිඩයේ විශේෂිත අගයක් සොයනු ඇත (උදා: පණිවිඩයේ "xyz" සොයන්නේ "හඳුනා නොගත් කේතය 'xyz' ").
රොඩ්නි ගිට්සෙල්

3
මම හිතන්නේ නැම්ෂුබ් රයිටර්ගේ ප්‍රවේශය ඔබට ලෝක දෙකෙන්ම හොඳම දේ ලබා දෙයි.
එඩී

4
ExpectedException භාවිතා කිරීමෙන් ඔබට මෙම ව්‍යතිරේකය මෙන් පරීක්ෂා කිරීම සඳහා එක් ක්‍රමයකට N exception.expect ලෙස හැඳින්විය හැකිය. Expect (IndexOutOfBoundsException.class); foo.doStuff1 (); exception.expect (IndexOutOfBoundsException.class); foo.doStuff2 (); exception.expect (IndexOutOfBoundsException.class); foo.doStuff3 ();
user1154664

10
@ user1154664 ඇත්තටම ඔබට බැහැ. ExpectedException භාවිතා කිරීමෙන් ඔබට පරීක්ෂා කළ හැක්කේ එක් ක්‍රමයක් ව්‍යතිරේකයක් විසි කරන බව පමණි, මන්ද එම ක්‍රමය හැඳින්වූ විට, පරීක්ෂණය අපේක්ෂිත ව්‍යතිරේකය විසි කළ නිසා එය ක්‍රියාත්මක වීම නවත්වනු ඇත!
නම්ෂුබ් රයිටර්

2
ඔබේ පළමු වාක්‍යය සත්‍ය නොවේ. භාවිතා කරන විට ExpectedException, කළ යුතු සාමාන්‍ය දෙය නම්, ව්‍යතිරේකය විසි කිරීමට ඔබ අපේක්ෂා කරන රේඛාවට පෙර අපේක්ෂාව වහාම සකස් කිරීමයි. ඒ ආකාරයෙන්, පෙර පේළියක් ව්‍යතිරේකය විසි කළහොත්, එය රීතිය අවුලුවන්නේ නැති අතර පරීක්ෂණය අසාර්ථක වනු ඇත.
ඩාවුඩ් ඉබ්න් කරීම්

213

පෙර පිළිතුරු දුන් පරිදි, JUnit හි ව්‍යතිරේකයන් සමඟ කටයුතු කිරීමට බොහෝ ක්‍රම තිබේ. නමුත් ජාවා 8 සමඟ තවත් එකක් තිබේ: ලැම්බඩා ප්‍රකාශන භාවිතා කිරීම. ලැම්බඩා ප්‍රකාශන සමඟ අපට මෙවැනි වාක්‍ය ඛණ්ඩයක් ලබා ගත හැකිය:

@Test
public void verifiesTypeAndMessage() {
    assertThrown(new DummyService()::someMethod)
            .isInstanceOf(RuntimeException.class)
            .hasMessage("Runtime exception occurred")
            .hasMessageStartingWith("Runtime")
            .hasMessageEndingWith("occurred")
            .hasMessageContaining("exception")
            .hasNoCause();
}

assertThrown විසින් ක්‍රියාකාරී අතුරු මුහුණතක් පිළිගනී, එහි අවස්ථා ලැම්බඩා ප්‍රකාශන, ක්‍රම යොමු හෝ ඉදිකිරීම්කරුවන්ගේ යොමු කිරීම් සමඟ නිර්මාණය කළ හැකිය. එම අතුරුමුහුණත පිළිගැනීම ව්‍යතිරේකයක් හැසිරවීමට සූදානම් වනු ඇත.

මෙය සාපේක්ෂව සරල නමුත් බලවත් තාක්‍ෂණයකි.

මෙම තාක්ෂණය විස්තර කරන මෙම බ්ලොග් සටහන බලන්න: http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

ප්‍රභව කේතය මෙතැනින් සොයාගත හැකිය: https://github.com/kolorobot/unit-testing-demo/tree/master/src/test/java/com/github/kolorobot/exceptions/java8

අනාවරණය: මම බ්ලොග් අඩවියේ සහ ව්‍යාපෘතියේ කතුවරයා වෙමි.


2
මම මෙම විසඳුමට කැමතියි නමුත් මට මේවන් රෙපෝ එකකින් බාගත කළ හැකිද?
සෙල්වින්

අදහස මාවන්හි ඇති මෙම අදහස ක්‍රියාත්මක කිරීම පළමු පියවර වන්නේ stefanbirkner.github.io/vallado
NamshubWriter

6
API ක්‍රිස්ටියානෝ ෆොන්ටස් මෙම API හි සරල අනුවාදය JUnit 4.13 සඳහා නියම කර ඇත. Github.com/junit-team/junit/commit/…
NamshubWriter

AfRafalBorowiec තාක්‍ෂණිකව, new DummyService()::someMethoda MethodHandle, නමුත් මෙම ප්‍රවේශය ලැම්බඩා ප්‍රකාශන සමඟ සමානව ක්‍රියා කරයි.
ඇන්ඩි

@NamshubWriter, එය junit 4.13 junit 5 පක්ෂව අතහැර දමා ඇති බව පෙනේ: stackoverflow.com/questions/156503/...
Vadzim

156

ජුනිට් හි, ව්‍යතිරේකය පරීක්ෂා කිරීමට ක්‍රම හතරක් ඇත.

junit5.x

  • junit5.x සඳහා, ඔබට assertThrowsපහත පරිදි භාවිතා කළ හැකිය

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        Throwable exception = assertThrows(IndexOutOfBoundsException.class, () -> foo.doStuff());
        assertEquals("expected messages", exception.getMessage());
    }

junit4.x

  • junit4.x සඳහා, ටෙස්ට් ව්‍යාකරණයේ විකල්ප 'අපේක්ෂිත' ගුණාංගය භාවිතා කරන්න

    @Test(expected = IndexOutOfBoundsException.class)
    public void testFooThrowsIndexOutOfBoundsException() {
        foo.doStuff();
    }
  • junit4.x සඳහා, ExpectedException රීතිය භාවිතා කරන්න

    public class XxxTest {
        @Rule
        public ExpectedException thrown = ExpectedException.none();
    
        @Test
        public void testFooThrowsIndexOutOfBoundsException() {
            thrown.expect(IndexOutOfBoundsException.class)
            //you can test the exception message like
            thrown.expectMessage("expected messages");
            foo.doStuff();
        }
    }
  • ජුනිට් 3 රාමුව යටතේ ඔබට බහුලව භාවිතා වන සම්භාව්‍ය උත්සාහ / අල්ලා ගැනීමේ ක්‍රමය භාවිතා කළ හැකිය

    @Test
    public void testFooThrowsIndexOutOfBoundsException() {
        try {
            foo.doStuff();
            fail("expected exception was not occured.");
        } catch(IndexOutOfBoundsException e) {
            //if execution reaches here, 
            //it indicates this exception was occured.
            //so we need not handle it.
        }
    }
  • නිසා

    • ඔබ ජුනිට් 5 ට කැමති නම්, ඔබ පළමු එකට කැමති විය යුතුය
    • 2 වන ක්‍රමය භාවිතා කරනුයේ ඔබට ව්‍යතිරේක වර්ගය පරීක්ෂා කිරීමට අවශ්‍ය වූ විට පමණි
    • ඔබට තවත් පරීක්ෂණ ව්‍යතිරේක පණිවිඩයක් අවශ්‍ය වූ විට පළමු හා අවසාන දෙක භාවිතා වේ
    • ඔබ ජුනිට් 3 භාවිතා කරන්නේ නම්, 4 වන එක වඩාත් සුදුසු වේ
  • වැඩිදුර තොරතුරු සඳහා, ඔබ කියවිය හැකි මෙම ලියවිල්ල හා junit5 පරිශීලක අත්පොත විස්තර සඳහා.


6
මට නම් මෙය හොඳම පිළිතුරයි, එය සියලු ආකාර ඉතා පැහැදිලිව ආවරණය කරයි, ස්තූතියි! පුද්ගලිකව මම කියවීමේ හැකියාව සඳහා ජුනිට් 4 සමඟ පවා 3 වන විකල්පය භාවිතා කරමි, හිස් ඇල්ලීම වළක්වා ගැනීම සඳහා ඔබට විසි කළ හැකි සහ තහවුරු කළ හැකි ඊ
නිකොලස් කෝර්නෙට්

පරීක්ෂා කරන ලද ව්‍යතිරේකයක් අපේක්ෂා කිරීම සඳහා ExpectedException භාවිතා කළ හැකිද?
miuser

ඒ සියල්ලම ඉහළම පිළිතුරු තුනේ සමුච්චය කිරීම පමණි. IMO, මෙම පිළිතුර අළුත් කිසිවක් එකතු නොකරන්නේ නම් එය පළ නොකළ යුතුය. නියෝජිතයාට පිළිතුරු දීම (ජනප්‍රිය ප්‍රශ්නයක්). තරමක් නිෂ් .ලයි.
පෝල් සංසෝතා

නිසැකවම, ඔබට Trowableක්‍රමයට ව්‍යුත්පන්න කළ ඕනෑම වර්ගයක් සමත් විය හැකි බැවිනි ExpectedException.expect. කරුණාකර එය අත්සන බලන්න . @miuser
වොල්ෂ්

118

tl; dr

  • පශ්චාත්-ජේඩීකේ 8: සුවිශේෂී හැසිරීම තහවුරු කිරීම සඳහා ඇසර්ට් ජේ හෝ අභිරුචි ලැම්බඩාස් භාවිතා කරන්න .

  • පෙර JDK8: මම පැරණි හොඳ try- catchවාරණය නිර්දේශ කරමි . ( වාරණයට පෙර ප්‍රකාශයක් එක් කිරීමට අමතක නොකරන්නfail()catch )

ජුනිට් 4 හෝ ජුනිට් 5 නොසලකා.

දිගු කතාව

ඔබට එය තනිවම කළ හැකිය try - catchJUnit මෙවලම් අවහිර කිරීම හෝ භාවිතා කිරීම ( @Test(expected = ...)හෝ@Rule ExpectedException JUnit රීති අංගය).

නමුත් මෙම ක්‍රම එතරම් අලංකාර නොවන අතර කියවීමේ හැකියාව වෙනත් මෙවලම් සමඟ හොඳින් මිශ්‍ර නොකරන්න . එපමණක් නොව, JUnit මෙවලම් වලට යම් යම් අන්තරායන් ඇත.

  1. මෙම try- catchඔබ පරීක්ෂා හැසිරීම අවට වාරණ ලියන්න හා උඩ කොටසේ එම ප්රකාශය ලිවීමට, ඒක හොඳයි නමුත් මේ ආකාරයේ පරීක්ෂණයක් කියවන ගලා බාදා බොහෝ සොයා විය හැකිය ඇති වාරණ. එසේම, ඔබ බ්ලොක් එක Assert.failඅවසානයේ ලිවිය යුතුය try. එසේ නොමැති නම්, පරීක්ෂණයෙන් ප්‍රකාශයේ එක් පැත්තක් මග හැරිය හැක; PMD , findbugs හෝ Sonar එවැනි ගැටළු හඳුනා ගනී.

  2. @Test(expected = ...)ඔබට අඩු කේතයක් ලිවිය හැකි බැවින් මෙම ලක්ෂණය සිත්ගන්නා සුළු වන අතර පසුව මෙම පරීක්ෂණය ලිවීම කේතීකරණ දෝෂ වලට ඇති ඉඩකඩ අඩුය. නමුත් මෙම ප්රවේශය සමහර ක්ෂේත්රවල අඩුපාඩු වේ.

    • පරීක්ෂණයට හේතුව හෝ පණිවිඩය වැනි ව්‍යතිරේකය පිළිබඳ අමතර කරුණු පරික්ෂා කිරීමට අවශ්‍ය නම් (හොඳ ව්‍යතිරේක පණිවිඩ ඇත්තෙන්ම වැදගත් ය, නිශ්චිත ව්‍යතිරේක වර්ගයක් තිබීම ප්‍රමාණවත් නොවනු ඇත).
    • පරීක්‍ෂා කළ කේතය ලියා ඇති ආකාරය මත පදනම්ව අපේක්ෂාව ක්‍රමවේදය තුළ තැන්පත් කර ඇති බැවින්, පරීක්ෂණ කේතයේ වැරදි කොටස ව්‍යතිරේකය විසි කළ හැකි අතර එය ව්‍යාජ-ධනාත්මක පරීක්ෂණයකට තුඩු දෙන අතර PMD , findbugs හෝ Sonar එවැනි කේතයක් පිළිබඳ ඉඟි ලබා දෙනු ඇත.

      @Test(expected = WantedException.class)
      public void call2_should_throw_a_WantedException__not_call1() {
          // init tested
          tested.call1(); // may throw a WantedException
      
          // call to be actually tested
          tested.call2(); // the call that is supposed to raise an exception
      }
  3. මෙම ExpectedExceptionපාලනය ද පෙර caveats විසින් අදාල කරුණ නිවැරදි කිරීමට උත්සාහ, නමුත්, එය බලාපොරොත්තු වීමයි ශෛලිය භාවිතා ලෙස භාවිතා කිරීමට ටිකක් අමුතු දැනෙනවා, EasyMock පරිශීලකයන් ඉතා හොඳින් මෙම වර්ගයේ දන්නවා. සමහරුන්ට එය පහසු විය හැකි නමුත්, ඔබ චර්යාත්මක ධාවක සංවර්ධනය (බීඩීඩී) හෝ ඇරේන්ජ් ඇක්ට් ඇසර්ට් (ඒඒඒ) මූලධර්ම අනුගමනය කරන්නේ ExpectedExceptionනම්, එම ලිවීමේ ශෛලියට රීතිය නොගැලපේ. ඒ හැරුණු විට @Test, ඔබ අපේක්ෂාව තබන ස්ථානය මත පදනම්ව, එය එකම ගැටලුවකින් පීඩා විඳින්නට පුළුවන .

    @Rule ExpectedException thrown = ExpectedException.none()
    
    @Test
    public void call2_should_throw_a_WantedException__not_call1() {
        // expectations
        thrown.expect(WantedException.class);
        thrown.expectMessage("boom");
    
        // init tested
        tested.call1(); // may throw a WantedException
    
        // call to be actually tested
        tested.call2(); // the call that is supposed to raise an exception
    }

    අපේක්ෂිත ව්‍යතිරේකය පවා පරීක්ෂණ ප්‍රකාශයට පෙර තබා ඇති අතර, පරීක්ෂණ BDD හෝ AAA අනුගමනය කරන්නේ නම් එය ඔබේ කියවීමේ ප්‍රවාහය බිඳ දමයි.

    එසේම, කර්තෘගේ ජුනිට් පිළිබඳ මෙම අදහස් දැක්වීමේ ගැටලුව බලන්න ExpectedException. JUnit 4.13-beta-2 පවා මෙම යාන්ත්‍රණය ප්‍රතික්ෂේප කරයි:

    ඉල්ලීම අදින්න # 1519 : අපේක්ෂිත ව්‍යතිරේකය ඉවත් කරන්න

    Assert.assertThrows ක්‍රමය ව්‍යතිරේක සත්‍යාපනය සඳහා වඩාත් හොඳ ක්‍රමයක් සපයයි. ඊට අමතරව, ටෙස්ට් වොචර් වැනි වෙනත් රීති සමඟ භාවිතා කරන විට එක්ස්පෙක්ටඩ්එක්සෙප්ෂන් භාවිතය දෝෂ සහිත වේ, මන්ද එම අවස්ථාවේ දී නීති අනුපිළිවෙල වැදගත් වේ.

එබැවින් මෙම ඉහත විකල්පයන් තුළ ඔවුන්ගේ සියලු අවවාද රාශියක් ඇති අතර පැහැදිලිවම කේත කේත දෝෂ වලින් නිදහස් නොවේ.

  1. මම පෙනුම, එය විසින් පොරොන්දු මේ පිළිතුර නිර්මාණය පසු දැනුවත් විය ව්යාපෘතියක් තියෙනවා උඩ-හැර .

    ව්‍යාපෘතියේ විස්තරය පවසන පරිදි, එය ව්‍යතිරේකය හසුකර ගැනීමට කේත රචකයෙකුට චතුර ලෙස පේළියක ලිවීමට ඉඩ සලසයි. ඔබට හැම්ක්‍රෙස්ට් හෝ ඇසර්ට් ජේ වැනි ඕනෑම ප්‍රකාශ පුස්තකාලයක් භාවිතා කළ හැකිය .

    මුල් පිටුවෙන් ලබාගත් වේගවත් උදාහරණයක්:

    // given: an empty list
    List myList = new ArrayList();
    
    // when: we try to get the first element of the list
    when(myList).get(1);
    
    // then: we expect an IndexOutOfBoundsException
    then(caughtException())
            .isInstanceOf(IndexOutOfBoundsException.class)
            .hasMessage("Index: 1, Size: 0") 
            .hasNoCause();

    කේතය සැබවින්ම සරල බව ඔබට පෙනෙන පරිදි, ඔබ විශේෂිත රේඛාවකින් ව්‍යතිරේකය අල්ලා ගනී, thenඒපීඅයි යනු අන්වර්ථයකි, එය AssertJ API භාවිතා කරයි (භාවිතයට සමාන assertThat(ex).hasNoCause()...). යම් අවස්ථාවක දී මෙම ව්‍යාපෘතිය ඇසර්ට් ජේගේ මුතුන් මිත්තෙකු වන ෆෙස්ට්-ඇසර්ට් මත රඳා පැවතුනි . සංස්කරණය කරන්න: මෙම ව්‍යාපෘතිය ජාවා 8 ලැම්බඩාස් සහය ලබා දෙන බව පෙනේ.

    දැනට, මෙම පුස්තකාලයේ අඩුපාඩු දෙකක් තිබේ:

    • මෙම ලිපිය ලියන අවස්ථාවේ දී, මෙම පුස්තකාලය මොකිටෝ 1.x මත පදනම් වී ඇති බව පැවසීම සැලකිය යුතු කරුණකි, මන්ද එය තිරය පිටුපස පරීක්ෂා කරන ලද වස්තුවක විහිළුවක් නිර්මාණය කරයි. මොකිටෝ තවමත් යාවත්කාලීන කර නොමැති බැවින් මෙම පුස්තකාලයට අවසාන පන්ති හෝ අවසාන ක්‍රම සමඟ වැඩ කළ නොහැක . එය වර්තමාන අනුවාදයේ මොකිටෝ 2 මත පදනම් වූවක් වුවද, මේ සඳහා ගෝලීය ව්‍යාජ නිෂ්පාදකයෙකු ( inline-mock-maker) ප්‍රකාශයට පත් කිරීම අවශ්‍ය වනු ඇත, ඔබට අවශ්‍ය නොවන දෙයක් විය හැකිය, මන්ද මෙම විහිළු සාදන්නාට සාමාන්‍ය විහිළු සාදන්නාගේ විවිධ අඩුපාඩු තිබේ.

    • එයට තවත් පරීක්ෂණ පරායත්තතාවයක් අවශ්‍ය වේ.

    පුස්තකාලය ලැම්බඩාස් සඳහා සහය දුන් පසු මෙම ගැටළු අදාළ නොවේ. කෙසේ වෙතත්, ක්‍රියාකාරීත්වය AssertJ මෙවලම් කට්ටලය විසින් අනුපිටපත් කරනු ලැබේ.

    අල්ලා ගැනීමේ ව්‍යතිරේක මෙවලම භාවිතා කිරීමට ඔබට අවශ්‍ය නැතිනම් සියල්ල සැලකිල්ලට ගනිමින් , අවම වශයෙන් JDK7 දක්වා try- catchබ්ලොක් හි පැරණි හොඳ ක්‍රමය මම නිර්දේශ කරමි . JDK 8 භාවිතා කරන්නන් සඳහා ඔබ AssertJ භාවිතා කිරීමට කැමති විය හැකිය.

  2. JDK8 සමඟ, ලැම්බඩාස් පරීක්ෂණ ස්ථානයට ඇතුළු වන අතර, ඔවුන් සුවිශේෂී හැසිරීම් තහවුරු කිරීමට සිත්ගන්නා ක්‍රමයක් බව ඔප්පු කර ඇත. සුවිශේෂී හැසිරීම තහවුරු කිරීම සඳහා හොඳ චතුර කථික API ලබා දීම සඳහා AssertJ යාවත්කාලීන කර ඇත.

    සහ AssertJ සමඟ නියැදි පරීක්ෂණයක් :

    @Test
    public void test_exception_approach_1() {
        ...
        assertThatExceptionOfType(IOException.class)
                .isThrownBy(() -> someBadIOOperation())
                .withMessage("boom!"); 
    }
    
    @Test
    public void test_exception_approach_2() {
        ...
        assertThatThrownBy(() -> someBadIOOperation())
                .isInstanceOf(Exception.class)
                .hasMessageContaining("boom");
    }
    
    @Test
    public void test_exception_approach_3() {
        ...
        // when
        Throwable thrown = catchThrowable(() -> someBadIOOperation());
    
        // then
        assertThat(thrown).isInstanceOf(Exception.class)
                          .hasMessageContaining("boom");
    }
  3. JUnit 5 නැවත ලිවීමත් සමඟම, ප්‍රකාශයන් ටිකක් වැඩි දියුණු කර ඇති අතර, නිසි ලෙස ව්‍යතිරේකයක් ඇති බව තහවුරු කර ගැනීම සඳහා ඒවා කොටුවෙන් පිටත සිත්ගන්නා සුළු විය හැකිය. නමුත් ඇත්ත වශයෙන්ම ප්‍රකාශ කිරීමේ API තවමත් ටිකක් දුර්වලයි, පිටතින් කිසිවක් නැත assertThrows.

    @Test
    @DisplayName("throws EmptyStackException when peeked")
    void throwsExceptionWhenPeeked() {
        Throwable t = assertThrows(EmptyStackException.class, () -> stack.peek());
    
        Assertions.assertEquals("...", t.getMessage());
    }

    ඔබ දුටු assertEqualsපරිදි තවමත් නැවත පැමිණේvoid , ඒ නිසා AssertJ වැනි දම්වැල් ප්‍රකාශයන්ට ඉඩ නොදේ.

    එසේම ඔබට නම් ගැටුම මතක නම් Matcherහෝ Assertඑකම ගැටුමකට මුහුණ දීමට සූදානම්ව සිටින්න Assertions.

අද (2017-03-03) AssertJ හි භාවිතයේ පහසුව, සොයාගත හැකි API, සංවර්ධනයේ වේගවත් වේගය සහ තථ්‍ය පරීක්ෂණ පරායත්තතාවය JDK8 සමඟ පරීක්ෂණ රාමුව නොසලකා JDK8 සමඟ ඇති හොඳම විසඳුම බව මම නිගමනය කිරීමට කැමැත්තෙමි (JUnit හෝ නැත), පෙර JDKs ඒ මත විශ්වාසය තැබිය යුතුය try-catch අවහිරතා .

මෙම පිළිතුර එකම දෘශ්‍යතාවයක් නොමැති වෙනත් ප්‍රශ්නයකින් පිටපත් කර ඇත , මම එකම කතුවරයා වෙමි.


1
Org.junit.jupiter: junit-jupiter-engine: 5.0.0-RC2 යැපීම (දැනටමත් පවතින ජුනිට් වලට අමතරව: junit: 4.12) assertThrows භාවිතා කිරීමට හැකිවීම සමහර විට වඩාත් සුදුසු විසඳුම නොවේ, නමුත් කිසිදු හේතුවක් ඇති නොවීය මට ප්‍රශ්න.
anre

මම ExpectedException රීතිය භාවිතා කිරීමේ රසිකයෙක් නමුත් එය AAA සමඟ බිඳී යාම සැමවිටම මට කරදරයක් විය. විවිධ ප්‍රවේශයන් විස්තර කිරීම සඳහා ඔබ විශිෂ්ට ලිපියක් ලියා ඇති අතර ඔබ නිසැකවම AssertJ උත්සාහ කිරීමට මා දිරිමත් කර ඇත :-) ස්තූතියි!
Pim Hazebroek

ImPimHazebroek ස්තූතියි. AssertJ API තරමක් පොහොසත් ය. මගේ මතය අනුව ජූනිට් යෝජනා කරන දේ කොටුවෙන් පිටත.
බ්‍රයිස්

64

දැන් JUnit 5 සහ JUnit 4.13 නිකුත් කර ඇති විට, හොඳම විකල්පය වනුයේ Assertions.assertThrows() (JUnit 5 සඳහා) සහ Assert.assertThrows()(JUnit 4.13 සඳහා) භාවිතා කිරීමයි. බලන්න Junit 5 පරිශීලක මාර්ගෝපදේශය .

ව්‍යතිරේකයක් විසි කර ඇති බව සනාථ කරන උදාහරණයක් මෙන්න, සහ ව්‍යතිරේක පණිවිඩය පිළිබඳ ප්‍රකාශ කිරීමට සත්‍යය භාවිතා කරයි :

public class FooTest {
  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    IndexOutOfBoundsException e = assertThrows(
        IndexOutOfBoundsException.class, foo::doStuff);

    assertThat(e).hasMessageThat().contains("woops!");
  }
}

අනෙක් පිළිතුරු වල ප්‍රවේශයන්ට වඩා වාසි:

  1. JUnit තුළට සාදා ඇත
  2. ලැම්බඩා හි කේතය ව්‍යතිරේකයක් නොදක්වන්නේ නම් ඔබට ප්‍රයෝජනවත් ව්‍යතිරේක පණිවිඩයක් ලැබෙනු ඇත.
  3. සංක්ෂිප්ත
  4. පිළිවෙල-පනත-තහවුරු කිරීම අනුගමනය කිරීමට ඔබගේ පරීක්ෂණ වලට ඉඩ දෙන්න
  5. ව්‍යතිරේකය විසි කිරීමට ඔබ අපේක්ෂා කරන්නේ කුමන කේතයද යන්න ඔබට හරියටම සඳහන් කළ හැකිය
  6. throwsවගන්තියේ අපේක්ෂිත ව්‍යතිරේකය ලැයිස්තුගත කිරීමට ඔබට අවශ්‍ය නැත
  7. අල්ලා ගත් ව්‍යතිරේකය පිළිබඳව ප්‍රකාශ කිරීම සඳහා ඔබට කැමති තේරීමේ රාමුවක් භාවිතා කළ හැකිය

ඒ හා සමාන ක්‍රමයක් org.junit AssertJUnit 4.13 හි එකතු වේ .


මෙම ප්‍රවේශය පිරිසිදුව ඇත, නමුත් මෙය අපගේ පරීක්ෂණයට "විධිවිධාන-පනත-තහවුරු කිරීම" අනුගමනය කිරීමට ඉඩ දෙන්නේ කෙසේදැයි මම නොදනිමි, මන්දයත් අපට "පනත" කොටස "assertThrow" හි ඔතා තැබිය යුතු අතර එය තහවුරු කිරීමකි.
ඔරලෝසු වැඩ

Lock ඔරලෝසු වැඩ කිරීම ලැම්බඩා යනු "ක්‍රියාව" ය. Arrange-Act-Assert හි පරමාර්ථය වන්නේ කේතය පිරිසිදුව හා සරල කිරීමයි (එබැවින් තේරුම් ගැනීමට සහ නඩත්තු කිරීමට පහසුය). ඔබ සඳහන් කළ පරිදි, මෙම ප්රවේශය පිරිසිදු ය.
නම්ෂුබ් රයිටර්

ටෙස්ට් අවසානයේදී විසිකිරීම සහ ව්‍යතිරේකය "ස්ථීර" කොටසේ ප්‍රකාශ කළ හැකි යැයි මම තවමත් සිතුවෙමි. මෙම ප්‍රවේශයේදී, ක්‍රියාව මුලින්ම අල්ලා ගැනීම සඳහා ඔබ පළමු ප්‍රකාශය ඔතා තැබිය යුතුය.
ඔරලෝසු වැඩ

ඒ සඳහා සෑම පරීක්ෂණයකදීම වැඩි කේතයක් අවශ්‍ය වේ. එය තවත් කේතයක් වන අතර එය දෝෂ සහිත වේ.
නම්ෂුබ් රයිටර්

43

මෙය සිදු වන්නේ කෙසේද: ඉතා සාමාන්‍ය ව්‍යතිරේකයක් අල්ලා ගන්න, එය එය ඇල්ලීමේ කොටසින් පිටතට ගෙන යන බවට වග බලා ගන්න, ඉන්පසු ව්‍යතිරේකයේ පන්තිය ඔබ බලාපොරොත්තු වන දෙය බව තහවුරු කරන්න. අ) ව්‍යතිරේකය වැරදි ආකාරයේ නම් (උදා: ඔබට ඒ වෙනුවට ශුන්‍ය දර්ශකයක් ලැබුනේ නම්) සහ ආ) ව්‍යතිරේකය කිසි විටෙකත් විසි නොකළේ නම් මෙම ප්‍රකාශය අසාර්ථක වනු ඇත.

public void testFooThrowsIndexOutOfBoundsException() {
  Throwable e = null;

  try {
    foo.doStuff();
  } catch (Throwable ex) {
    e = ex;
  }

  assertTrue(e instanceof IndexOutOfBoundsException);
}

3
එසේම, පරීක්ෂණය අසමත් වූ දිනය පැමිණෙන විට පරීක්ෂණ ප්‍රති results ලවල කුමන ආකාරයේ ව්‍යතිරේක හිටපුදැයි ඔබට නොපෙනේ.
jontejj

ඔබ අවසානයේ ප්‍රකාශ කරන ආකාරය වෙනස් කිරීමෙන් මෙය ටිකක් වැඩි දියුණු කළ හැකිය. assertEquals(ExpectedException.class, e.getClass())පරීක්ෂණය අසමත් වූ විට අපේක්ෂිත හා සත්‍ය අගයන් ඔබට පෙන්වනු ඇත.
සයිෆර්

37

BDD විලාසිතාවේ විසඳුම: JUnit 4 + Catch Exception + AssertJ

import static com.googlecode.catchexception.apis.BDDCatchException.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {

    when(() -> foo.doStuff());

    then(caughtException()).isInstanceOf(IndexOutOfBoundsException.class);

}

යැපීම්

eu.codearte.catch-exception:catch-exception:2.0

36

JUnit සමඟ භාවිතා කළ හැකි AssertJ ප්‍රකාශයක් භාවිතා කිරීම :

import static org.assertj.core.api.Assertions.*;

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  Foo foo = new Foo();

  assertThatThrownBy(() -> foo.doStuff())
        .isInstanceOf(IndexOutOfBoundsException.class);
}

එය @Test(expected=IndexOutOfBoundsException.class)පරීක්‍ෂණයේ අපේක්ෂිත රේඛාව ව්‍යතිරේකය විසි කළ බවට සහතික වන නිසා සහ පණිවුඩය වැනි ව්‍යතිරේකය පිළිබඳ වැඩි විස්තර පරීක්ෂා කිරීමට ඔබට ඉඩ සලසයි.

assertThatThrownBy(() ->
       {
         throw new Exception("boom!");
       })
    .isInstanceOf(Exception.class)
    .hasMessageContaining("boom");

Maven / Gradle උපදෙස් මෙහි.


ඉතා සංක්ෂිප්ත ආකාරයකින් හා කිසිවෙකු එය අගය නොකරයි, අමුතුයි .. මට ඇත්තේ එක් ප්‍රශ්නයක් පමණි assertJ පුස්තකාලය, assertThat ගැටුම් නම් අනුව නැණවත් ලෙස ජුනිට් සමඟ. assertJ throwby ගැන වැඩි විස්තර: JUnit: ජාවා 8 සහ AssertJ 3.0.0 සමඟ ව්‍යතිරේක පරීක්ෂා කිරීම ~ Codeleak.pl
ycomp

@ycomp හොඳයි එය ඉතා පැරණි ප්‍රශ්නයකට නව පිළිතුරකි, එබැවින් ලකුණු වෙනස රැවටිලිකාර ය.
වෙස්ටන්

කෙනෙකුට ජාවා 8 සහ ඇසර්ට් ජේ භාවිතා කළ හැකි නම් එය හොඳම විසඳුමයි!
පියරේ හෙන්රි

comycomp මෙම නම ගැටුම සැලසුම් අනුව විය හැකි යැයි මම සැක කරමි: එබැවින් AssertJ පුස්තකාලය ඔබව කිසි විටෙකත් JUnit භාවිතා නොකරන ලෙස තරයේ දිරිමත් assertThatකරයි. එසේම JUnit ක්‍රමය නැවත ලබා දෙන්නේ “නිත්‍ය” වර්ගයක් පමණක් වන අතර, AssertJ ක්‍රමය AbstractAssertඋප පංතියක් ලබා දෙයි ... ඉහත ක්‍රම ක්‍රම කිරීමට ඉඩ දෙයි (හෝ මේ සඳහා තාක්ෂණික යෙදුම් කුමක් වුවත් ...).
මයික් මීයන්

@weston ඇත්ත වශයෙන්ම මම ඔබේ තාක්‍ෂණය AssertJ 2.0.0 හි භාවිතා කර ඇත්තෙමි. උත්ශ්‍රේණි නොකිරීමට නිදහසට කරුණක් නැත, සැකයක් නැත, නමුත් ඔබ දැන ගැනීමට කැමති වුවද.
මයික් මීයන්

33

එම ගැටළුව විසඳීම සඳහා මම කුඩා ව්‍යාපෘතියක් ආරම්භ කළෙමි: http://code.google.com/p/catch-exception/

මෙම කුඩා සහායකයා භාවිතා කරමින් ඔබ ලියනු ඇත

verifyException(foo, IndexOutOfBoundsException.class).doStuff();

මෙය JUnit 4.7 හි ExpectedException රීතියට වඩා අඩු වාචික වේ. ස්කැෆ්මන් විසින් සපයන ලද විසඳුමට සාපේක්ෂව, ඔබ ව්‍යතිරේකය අපේක්ෂා කරන්නේ කුමන කේත රේඛාවෙන්ද යන්න ඔබට නියම කළ හැකිය. මම හිතනවා මේක උදව් වෙයි කියලා.


මමත් මේ වගේ දෙයක් කරන්න හිතුවා, නමුත් අවසානයේදී සොයාගත්තේ ExpectedException හි සැබෑ බලය නම් ඔබට අපේක්ෂිත ව්‍යතිරේකය නියම කළ හැකිවා පමණක් නොව, අපේක්ෂිත හේතුව හෝ අපේක්ෂිත පණිවිඩය වැනි ව්‍යතිරේකයේ සමහර ගුණාංගද නියම කළ හැකිය.
ජේසන් තොම්සන්

මගේ අනුමානය නම්, මෙම විසඳුමට සමච්චල් කිරීම් හා සමාන අඩුපාඩු තිබේද? උදාහරණයක් ලෙස, නම් fooවේ finalඑය ඔබ ප්රොක්සි නොහැකි නිසා අසාර්ථක වනු ඇත foo?
ටොම්

ටොම්, doStuff () අතුරු මුහුණතක කොටසක් නම් ප්‍රොක්සි ප්‍රවේශය ක්‍රියාත්මක වේ. එසේ නොමැතිනම් මෙම ප්‍රවේශය අසාර්ථක වනු ඇත, ඔබ හරි.
rwitzel

31

යාවත්කාලීන කිරීම: ව්‍යතිරේක පරීක්ෂණ සඳහා JUnit5 වැඩි දියුණු කිරීමක් ඇත:assertThrows .

පහත උදාහරණය: ජුනිට් 5 පරිශීලක මාර්ගෝපදේශය

 @Test
void exceptionTesting() {
    Throwable exception = assertThrows(IllegalArgumentException.class, () -> 
    {
        throw new IllegalArgumentException("a message");
    });
    assertEquals("a message", exception.getMessage());
}

JUnit 4 භාවිතා කරමින් මුල් පිළිතුර.

ව්යතිරේකයක් විසි කර ඇති බව පරීක්ෂා කිරීමට ක්රම කිහිපයක් තිබේ. මගේ පෝස්ට් එකේ පහත විකල්පයන් ගැනද සාකච්ඡා කර ඇත්තෙමිJUnit සමඟ විශිෂ්ට ඒකක පරීක්ෂණ ලියන්නේ කෙසේද යන්න ලිපියේ

expectedපරාමිතිය සකසන්න @Test(expected = FileNotFoundException.class).

@Test(expected = FileNotFoundException.class) 
public void testReadFile() { 
    myClass.readFile("test.txt");
}

භාවිතා කිරීම try catch

public void testReadFile() { 
    try {
        myClass.readFile("test.txt");
        fail("Expected a FileNotFoundException to be thrown");
    } catch (FileNotFoundException e) {
        assertThat(e.getMessage(), is("The file test.txt does not exist!"));
    }
     
}

ExpectedExceptionරීතිය සමඟ පරීක්ෂා කිරීම .

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

@Test
public void testReadFile() throws FileNotFoundException {
    
    thrown.expect(FileNotFoundException.class);
    thrown.expectMessage(startsWith("The file test.txt"));
    myClass.readFile("test.txt");
}

ව්‍යතිරේක පරීක්ෂාව සහ bad.robot සඳහා JUnit4 විකියෙහි ව්‍යතිරේක පරීක්ෂණ ගැන ඔබට වැඩිදුර කියවිය හැකිය - ව්‍යතිරේක අපේක්ෂා කිරීම JUnit Rule .


22

ඔබට මෙයද කළ හැකිය:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
    try {
        foo.doStuff();
        assert false;
    } catch (IndexOutOfBoundsException e) {
        assert true;
    }
}

12
JUnit පරීක්ෂණ වලදී, භාවිතා කිරීම වඩා හොඳය Assert.fail(), assertඔබේ පරීක්ෂණ ක්‍රියාත්මක කළ නොහැකි පරිසරයක ක්‍රියාත්මක වන්නේ නම් පමණක් නොවේ.
නම්ෂුබ් රයිටර්

14

IMHO, JUnit හි ව්‍යතිරේක පරීක්ෂා කිරීමට හොඳම ක්‍රමය වන්නේ උත්සාහ කිරීම / අල්ලා ගැනීම / අසමත් වීම / තහවුරු කිරීමේ රටාවයි:

// this try block should be as small as possible,
// as you want to make sure you only catch exceptions from your code
try {
    sut.doThing();
    fail(); // fail if this does not throw any exception
} catch(MyException e) { // only catch the exception you expect,
                         // otherwise you may catch an exception for a dependency unexpectedly
    // a strong assertion on the message, 
    // in case the exception comes from anywhere an unexpected line of code,
    // especially important if your checking IllegalArgumentExceptions
    assertEquals("the message I get", e.getMessage()); 
}

මෙම assertTrueසමහර අය සඳහා ටිකක් ශක්තිමත් විය හැකි, ඒ නිසා assertThat(e.getMessage(), containsString("the message");වඩාත් විය හැක.


13

JUnit 5 විසඳුම

@Test
void testFooThrowsIndexOutOfBoundsException() {    
  Throwable exception = expectThrows( IndexOutOfBoundsException.class, foo::doStuff );

  assertEquals( "some message", exception.getMessage() );
}

JUnit 5 පිළිබඳ වැඩි විස්තර http://junit.org/junit5/docs/current/user-guide/#writing-tests-assertions


expectThrows()ටෙස්ට්එන්ජී හි කොටසක් මිස ජුනිට් නොවේ
Lu55

13

ජුනිට් 4 සඳහා වඩාත් නම්‍යශීලී හා අලංකාර පිළිතුර මාක්යොං බ්ලොග් අඩවියෙන් මට හමු විය . එය ව්‍යාඛ්‍යාව try/catchභාවිතා කිරීමේ නම්‍යතාවය ඇත @Rule. අභිරුචි කළ ව්‍යතිරේකයක නිශ්චිත ගුණාංග ඔබට කියවිය හැකි නිසා මම මෙම ප්‍රවේශයට කැමතියි.

package com.mkyong;

import com.mkyong.examples.CustomerService;
import com.mkyong.examples.exception.NameNotFoundException;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.hasProperty;

public class Exception3Test {

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

    @Test
    public void testNameNotFoundException() throws NameNotFoundException {

        //test specific type of exception
        thrown.expect(NameNotFoundException.class);

        //test message
        thrown.expectMessage(is("Name is empty!"));

        //test detail
        thrown.expect(hasProperty("errCode"));  //make sure getters n setters are defined.
        thrown.expect(hasProperty("errCode", is(666)));

        CustomerService cust = new CustomerService();
        cust.findByName("");

    }

}

12

මම මෙහි බොහෝ ක්‍රම අත්හදා බැලුවෙමි, නමුත් ඒවා සංකීර්ණ හෝ මගේ අවශ්‍යතා සපුරාලීමට සමත් නොවීය. ඇත්ත වශයෙන්ම, කෙනෙකුට උපකාරක ක්‍රමයක් සරලව ලිවිය හැකිය:

public class ExceptionAssertions {
    public static void assertException(BlastContainer blastContainer ) {
        boolean caughtException = false;
        try {
            blastContainer.test();
        } catch( Exception e ) {
            caughtException = true;
        }
        if( !caughtException ) {
            throw new AssertionFailedError("exception expected to be thrown, but was not");
        }
    }
    public static interface BlastContainer {
        public void test() throws Exception;
    }
}

එය මේ ආකාරයට භාවිතා කරන්න:

assertException(new BlastContainer() {
    @Override
    public void test() throws Exception {
        doSomethingThatShouldExceptHere();
    }
});

ශුන්‍ය පරායත්තතා: මොකිටෝ අවශ්‍ය නැත, බල මෝක් අවශ්‍ය නොවේ; අවසාන පන්ති සමඟ හොඳින් ක්‍රියා කරයි.


සිත්ගන්නාසුළු නමුත් AAA (Arrange Act Assert) ට නොගැලපේ, එහිදී ඔබට පනත කිරීමට අවශ්‍ය වන අතර සත්‍ය වශයෙන්ම වෙනස් පියවරයන්හි සහතික කිරීමේ පියවර.
bln-tom

1
@ bln-tom තාක්ෂණික වශයෙන් එය වෙනස් පියවර දෙකකි, ඒවා එම අනුපිළිවෙලට නොවේ. ; p
ට්‍රෙජ්කාස්

10

ජාවා 8 විසඳුම

ඔබ විසඳුමකට කැමති නම්:

  • ජාවා 8 ලැම්බඩාස් භාවිතා කරයි
  • නැහැ නැහැ කිසිම JUnit මැජික් මත රඳා පවතී
  • තනි පරීක්ෂණ ක්‍රමයක් තුළ බහුවිධ ව්‍යතිරේක සඳහා පරීක්ෂා කිරීමට ඔබට ඉඩ දෙයි
  • සමස්ත පරීක්ෂණ ක්‍රමයේම නොදන්නා රේඛාවක් වෙනුවට ඔබේ පරීක්ෂණ ක්‍රමය තුළ නිශ්චිත රේඛා සමූහයක් විසින් ව්‍යතිරේකයක් සඳහා වන චෙක්පත්
  • විසි කළ සත්‍ය ව්‍යතිරේක වස්තුව ලබා දෙයි, එවිට ඔබට එය තවදුරටත් පරීක්ෂා කර බැලිය හැකිය

මෙන්න මම ලියූ උපයෝගිතා ශ්‍රිතයක්:

public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
    try
    {
        runnable.run();
    }
    catch( Throwable throwable )
    {
        if( throwable instanceof AssertionError && throwable.getCause() != null )
            throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
        assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
        assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
        @SuppressWarnings( "unchecked" )
        T result = (T)throwable;
        return result;
    }
    assert false; //expected exception was not thrown.
    return null; //to keep the compiler happy.
}

( මගේ බ්ලොග් අඩවියෙන් ගන්නා ලදි )

එය පහත පරිදි භාවිතා කරන්න:

@Test
public void testThrows()
{
    RuntimeException e = expectException( RuntimeException.class, () -> 
        {
            throw new RuntimeException( "fail!" );
        } );
    assert e.getMessage().equals( "fail!" );
}


8

මගේ නඩුවේදී මම සෑම විටම db වෙතින් RuntimeException ලබා ගනිමි, නමුත් පණිවිඩ වෙනස් වේ. ව්‍යතිරේකය පිළිවෙලින් හැසිරවිය යුතුය. මෙන්න මම එය පරීක්ෂා කළ ආකාරය:

@Test
public void testThrowsExceptionWhenWrongSku() {

    // Given
    String articleSimpleSku = "999-999";
    int amountOfTransactions = 1;
    Exception exception = null;

    // When
    try {
        createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
    } catch (RuntimeException e) {
        exception = e;
    }

    // Then
    shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}

private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
    assertNotNull(e);
    assertTrue(e.getMessage().contains(message));
}

1
රේඛාව සඳහා } catch (, ඔබ ඇතුළු කළ යුතුයfail("no exception thrown");
ඩැනියෙල් ඇල්ඩර්

6

මේ ආකාරයට ක්‍රියා විරහිත කර සක්‍රිය කළ හැකි මැචරයක් සාදන්න:

public class ExceptionMatcher extends BaseMatcher<Throwable> {
    private boolean active = true;
    private Class<? extends Throwable> throwable;

    public ExceptionMatcher(Class<? extends Throwable> throwable) {
        this.throwable = throwable;
    }

    public void on() {
        this.active = true;
    }

    public void off() {
        this.active = false;
    }

    @Override
    public boolean matches(Object object) {
        return active && throwable.isAssignableFrom(object.getClass());
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("not the covered exception type");
    }
}

එය භාවිතා කිරීමට:

එකතු කරන්න public ExpectedException exception = ExpectedException.none();, පසුව:

ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();

6

JUnit 4 හෝ ඊට පසු ඔබට ව්‍යතිරේකයන් පහත පරිදි පරීක්ෂා කළ හැකිය

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


මෙය අපගේ JUnit පරීක්ෂණ වැඩි දියුණු කිරීම සඳහා භාවිතා කළ හැකි විශේෂාංග රාශියක් සපයයි.
පහත උදාහරණය ඔබ දුටුවහොත් මම ව්‍යතිරේකය මත කරුණු 3 ක් පරීක්ෂා කරමි.

  1. ව්‍යතිරේකයේ වර්ගය විසි කර ඇත
  2. ව්යතිරේකය පණිවිඩය
  3. ව්යතිරේකයට හේතුව


public class MyTest {

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

    ClassUnderTest classUnderTest;

    @Before
    public void setUp() throws Exception {
        classUnderTest = new ClassUnderTest();
    }

    @Test
    public void testAppleisSweetAndRed() throws Exception {

        exceptions.expect(Exception.class);
        exceptions.expectMessage("this is the exception message");
        exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));

        classUnderTest.methodUnderTest("param1", "param2");
    }

}

6

ව්‍යතිරේකයක් ආපසු ලබා දිය යුතු ක්‍රමයට පසුව අපට ප්‍රකාශයක් අසාර්ථක විය හැකිය:

try{
   methodThatThrowMyException();
   Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
   // Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
   assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
   // In case of verifying the error message
   MyException myException = (MyException) exception;
   assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}

3
දෙවැන්න catchවෙනත් ව්‍යතිරේකයක් විසි කළ හොත් ප්‍රයෝජනවත් තොරතුරු නැති
වුවහොත් තොග හෝඩුවාව

5

NamShubWriter පවසා ඇති දේට අමතරව , එය සහතික කරගන්න:

  • අපේක්ෂිත එක්සෙප්ෂන් උදාහරණය පොදු ය ( අදාළ ප්‍රශ්නය )
  • මෙම ExpectedException නැත කිව්වොත්, මේ @Before ක්රමය තුළ instantiated. මෙම පෝස්ට් මගින් ජුනිට්ගේ මරණ ද order ුවම ක්‍රියාත්මක කිරීමේ සියලු සංකීර්ණතා පැහැදිලිව පැහැදිලි කරයි.

එපා නොවන මෙය කරන්න:

@Rule    
public ExpectedException expectedException;

@Before
public void setup()
{
    expectedException = ExpectedException.none();
}

අවසාන වශයෙන්, මෙම බ්ලොග් සටහන පැහැදිලිව පෙන්නුම් කරන්නේ කිසියම් ව්‍යතිරේකයක් විසි කර ඇති බව ප්‍රකාශ කරන්නේ කෙසේද යන්නයි.


4

assertj-coreජුනිට් පරීක්ෂණයෙන් ව්‍යතිරේකය හැසිරවීමට මම පුස්තකාලය නැවත නිර්දේශ කරමි

ජාවා 8 හි, මේ ආකාරයට:

//given

//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));

//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);

2

Java8 සමඟ Junit4 විසඳුම මෙම ශ්‍රිතය භාවිතා කිරීමයි:

public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
    try {
        funky.call();
    } catch (Throwable e) {
        if (expectedException.isInstance(e)) {
            return e;
        }
        throw new AssertionError(
                String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
    }
    throw new AssertionError(
            String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}

භාවිතය එවිට:

    assertThrows(ValidationException.class,
            () -> finalObject.checkSomething(null));

එකම සීමාව වන්නේ finalලැම්බඩා ප්‍රකාශනයේ වස්තු යොමු කිරීමක් බව සලකන්න . මෙම විසඳුම මඟින් විසඳුම් මට්ටමින් ක්‍රම මට්ටමින් බලාපොරොත්තු විය හැකි දේ වෙනුවට පරීක්ෂණ ප්‍රකාශ දිගටම කරගෙන යාමට ඉඩ ලබා දේ @Test(expected = IndexOutOfBoundsException.class).


1

උදාහරණයක් ලෙස, පහත දැක්වෙන කේත කැබැල්ල සඳහා ඔබට ජුනිට් ලිවීමට අවශ්‍යය

public int divideByZeroDemo(int a,int b){

    return a/b;
}

public void exceptionWithMessage(String [] arr){

    throw new ArrayIndexOutOfBoundsException("Array is out of bound");
}

ඉහත කේතය යනු සිදුවිය හැකි නොදන්නා ව්‍යතිරේකයක් සඳහා පරීක්ෂා කිරීම වන අතර පහත දැක්වෙන්නේ අභිරුචි පණිවිඩ සමඟ යම් ව්‍යතිරේකයක් ප්‍රකාශ කිරීමයි.

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

private Demo demo;
@Before
public void setup(){

    demo=new Demo();
}
@Test(expected=ArithmeticException.class)
public void testIfItThrowsAnyException() {

    demo.divideByZeroDemo(5, 0);

}

@Test
public void testExceptionWithMessage(){


    exception.expectMessage("Array is out of bound");
    exception.expect(ArrayIndexOutOfBoundsException.class);
    demo.exceptionWithMessage(new String[]{"This","is","a","demo"});
}

1
    @Test(expectedException=IndexOutOfBoundsException.class) 
    public void  testFooThrowsIndexOutOfBoundsException() throws Exception {
         doThrow(IndexOutOfBoundsException.class).when(foo).doStuff();  
         try {
             foo.doStuff(); 
            } catch (IndexOutOfBoundsException e) {
                       assertEquals(IndexOutOfBoundsException .class, ex.getCause().getClass());
                      throw e;

               }

    }

නිවැරදි ව්‍යතිරේකය විසි කර ඇත්දැයි පරීක්ෂා කිරීමට තවත් ක්‍රමයක් මෙන්න.


1

JUnit රාමුවට assertThrows()ක්‍රමයක් ඇත:

ArithmeticException exception = assertThrows(ArithmeticException.class, () ->
    calculator.divide(1, 0));
assertEquals("/ by zero", exception.getMessage());
  • JUnit 5 සඳහා එය ක්‍රියාත්මකයි org.junit.jupiter.api.Assertions පන්තියේ ය;
  • JUnit 4.13 සඳහා එය ක්‍රියාත්මකයි org.junit.Assert පන්තියේ ය;
  • JUnit 4 හි පෙර සංස්කරණ සඳහා: org.junit.jupiter:junit-jupiter-apiඔබේ ව්‍යාපෘතිය පිළිබඳ සඳහනක් එක් කරන්න, එවිට ඔබට JUnit 5 වෙතින් හොඳින් වැඩ කරන අනුවාදයක් ලැබෙනු ඇත.

0

ජාවා 8 සමඟ ඔබට පරික්ෂා කිරීමට කේතයක් ගන්නා ක්‍රමයක් සහ පරාමිතීන් ලෙස අපේක්ෂිත ව්‍යතිරේකය නිර්මාණය කළ හැකිය:

private void expectException(Runnable r, Class<?> clazz) { 
    try {
      r.run();
      fail("Expected: " + clazz.getSimpleName() + " but not thrown");
    } catch (Exception e) {
      if (!clazz.isInstance(e)) fail("Expected: " + clazz.getSimpleName() + " but " + e.getClass().getSimpleName() + " found", e);
    }
  }

ඉන්පසු ඔබේ පරීක්ෂණය ඇතුළත:

expectException(() -> list.sublist(0, 2).get(2), IndexOutOfBoundsException.class);

ප්‍රතිලාභ:

  • කිසිදු පුස්තකාලයක් මත රඳා නොසිටීම
  • දේශීයකරණය කළ චෙක්පත - වඩාත් නිරවද්‍ය වන අතර අවශ්‍ය නම් එක් පරීක්‍ෂණයක් තුළ මෙවැනි බහුවිධ ප්‍රකාශයන් කිරීමට ඉඩ ලබා දේ
  • භාවිතා කිරීමට පහසුය
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.