আমি কীভাবে আমার ব্যতিক্রম বার্তাটি JUnit টেস্ট টীকা দিয়ে জোর করব?


313

আমি @Testটীকা সহ কয়েকটি JUnit পরীক্ষা লিখেছি । যদি আমার পরীক্ষার পদ্ধতিটি যদি একটি চেক করা ব্যতিক্রম ছুঁড়ে ফেলেছে এবং আমি যদি ব্যতিক্রমের সাথে বার্তাটি জোড় করতে চাই তবে JUnit @Testটীকাগুলির সাথে কী করার উপায় আছে ? আফাইক, জুনিয়ট ৪.7 এই বৈশিষ্ট্যটি সরবরাহ করে না তবে ভবিষ্যতের কোনও সংস্করণ কী তা সরবরাহ করে? আমি জানি। নেট আপনি বার্তা এবং ব্যতিক্রম শ্রেণি জোড় করতে পারেন। জাভা বিশ্বে অনুরূপ বৈশিষ্ট্য খুঁজছেন।

এটাই আমি চাই:

@Test (expected = RuntimeException.class, message = "Employee ID is null")
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() {}

1
এখন যেহেতু আমি এটি সম্পর্কে আরও কিছু ভাবছি ... আপনি কি নিশ্চিত যে বার্তাটি চাপানো ভাল ধারণা? আপনার প্রশ্ন আমাকে জুনিট সোর্স কোডটি কিছুটা খনন করেছে এবং দেখে মনে হচ্ছে তারা সহজেই এই বৈশিষ্ট্যটি যুক্ত করতে পারত। তারা তা করেনি, তা আমাকে মনে করে যে এটি একটি ভাল অনুশীলন হিসাবে বিবেচিত হবে না। আপনার প্রকল্পে বার্তাটি চাপানো কেন গুরুত্বপূর্ণ?
সি_মেকার

9
ভাল প্রশ্ন। বলুন যে 15 টি লাইন কোড যুক্ত একটি পদ্ধতি 2 টি পৃথক স্থান থেকে একই ব্যতিক্রম ছোঁড়ে। আমার পরীক্ষার কেসগুলি কেবল ব্যতিক্রম শ্রেণি নয় এটিতে বার্তাটিও জোর দেওয়া দরকার। আদর্শ বিশ্বে যে কোনও অস্বাভাবিক আচরণের নিজস্ব ব্যতিক্রম হওয়া উচিত f যদি ঘটনাটি ঘটে থাকে তবে আমার প্রশ্নটি কখনই উত্থিত হত না তবে প্রোডাকশন অ্যাপ্লিকেশনগুলির প্রতিটি অস্বাভাবিক আচরণের জন্য তাদের অনন্য কাস্টম ব্যতিক্রম নেই।
Cshah

পার্শ্ব নোট হিসাবে - @expectedExceptionMessageপিএইচপিউইনেটে টিকা আছে।
ব্যাঙ্কার

উত্তর:


535

আপনি এর মতো @Ruleটিকাটি ব্যবহার করতে পারেন ExpectedException:

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

@Test
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() throws Exception {
    expectedEx.expect(RuntimeException.class);
    expectedEx.expectMessage("Employee ID is null");

    // do something that should throw the exception...
    System.out.println("=======Starting Exception process=======");
    throw new NullPointerException("Employee ID is null");
}

নোট করুন যে ExpectedExceptionদস্তাবেজের উদাহরণটি (বর্তমানে) ভুল - কোনও পাবলিক কনস্ট্রাক্টর নেই, তাই আপনাকে ব্যবহার করতে হবে ExpectedException.none()


1
দ্রষ্টব্য: আমার জন্য যখন expectMessageখালি স্ট্রিং হিসাবে নির্দিষ্ট করা হয়েছিল, বার্তার জন্য তুলনাটি সম্পাদন করা হয়নি
redDevil

1
আমার জন্য দরকারী। ধন্যবাদ। টেস্টমেডোথের throws RuntimeExceptionকোড যুক্ত করার পরে একটি ব্যতিক্রম ছুঁড়ে ফেলা উচিত । এটি
ধরবেন

5
আমি ব্যক্তিগতভাবে এটি ব্যবহার করতে চাই না কারণ ছোট পদ্ধতির একটি ছোট উপসর্গের উদ্দেশ্যে ক্ষেত্র তৈরি করা খারাপ অভ্যাস। প্রতিক্রিয়া নিয়ে একটি সমালোচনা নয়, কিন্তু ইউনিতের ডিজাইনের। ওপির হাইপোপটিকাল সলিউশন যদি এটি বিদ্যমান থাকে তবে তা আরও ভাল হবে।
শ্রীধর সারনোবাত

2
@ রেড ডেভিল: প্রত্যাশিত ম্যাসেজটি পরীক্ষা করে যদি ত্রুটি বার্তায় এই ফাংশনে নির্দিষ্ট করা স্ট্রিং "ত্রুটি বার্তার একটি স্ট্রিংয়ের মতো" থাকে
tuan.dinh

3
প্রত্যাশামাখা স্ট্রিং প্যারামিটার সহ একটি স্ট্রিং.কন্টেন পরীক্ষা করে থাকে, ব্যতিক্রমের বার্তার সঠিক ম্যাচের জন্য হামক্রেষ্ট ম্যাচার ব্যবহার করুনfailure.expectMessage(CoreMatchers.equalTo(...))
শিভাবালান

41

আমি @Ruleউত্তরটি পছন্দ করি । তবে, যদি কোনও কারণে আপনি নিয়ম ব্যবহার করতে চান না। তৃতীয় বিকল্প আছে।

@Test (expected = RuntimeException.class)
public void myTestMethod()
{
   try
   {
      //Run exception throwing operation here
   }
   catch(RuntimeException re)
   {
      String message = "Employee ID is null";
      assertEquals(message, re.getMessage());
      throw re;
    }
    fail("Employee Id Null exception did not throw!");
  }

6
পরীক্ষার অভ্যন্তরে চেষ্টা ক্যাচ যোগ করা ভাল অভ্যাস নয়
কার্লোস ল্যাপেজ মারি

32

আপনার কি ব্যবহার করতে হবে @Test(expected=SomeException.class)? যখন আমাদের ব্যতিক্রমের প্রকৃত বার্তাটি চাপিয়ে দিতে হয়, আমরা এটি করি।

@Test
public void myTestMethod()
{
  try
  {
    final Integer employeeId = null;
    new Employee(employeeId);
    fail("Should have thrown SomeException but did not!");
  }
  catch( final SomeException e )
  {
    final String msg = "Employee ID is null";
    assertEquals(msg, e.getMessage());
  }
}

6
আমি একটি ক্যাচ ব্লক লেখার বিষয়ে সচেতন এবং এর মধ্যে দৃsert়তা ব্যবহার করে তবে আরও ভাল কোড পঠনযোগ্যতার জন্য আমি টিকা দিয়ে করতে চাই।
Cshah

এছাড়াও "ডান" উপায়ে করার সময় আপনি যেমন কোনও সুন্দর বার্তা পাবেন না।
নেপলটানিউডাজ

15
ট্রাই / ক্যাচ সংস্করণে সমস্যা, এখন যে ইউনাইট সরবরাহ করে @Test(expected=...)এবং ExpectedExceptionএটি হ'ল আমি অনেকবার দেখেছি যে কেউ ব্লকের শেষে কল রাখতে ভুলেfail()try গিয়েছে । কোড পর্যালোচনা দ্বারা ধরা না পড়লে আপনার পরীক্ষাটি মিথ্যা-ইতিবাচক এবং সর্বদা পাস হতে পারে।
উইলিয়াম দাম

এই কারণেই আমি এই সমস্ত ঘোষণামূলক জিনিস পছন্দ করি না। আপনি যা চান তা অ্যাক্সেস করা শক্ত করে তোলে।
শ্রীধর সারনোবাত

30

JUnit 4.13 এ আপনি করতে পারেন:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

...

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

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

এটি 5 ইউনাইটেও বিভিন্ন আমদানি সহ কাজ করে :

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

...

এই সমাধানটি পছন্দ করুন। জুনেট 5 এ স্থানান্তরিত হওয়া উচিত
ওয়েস্টার্নগুন

Gaaaaaaaaa। 4.13 এখনও বিটা অবধি আজ (পতন, 2019)? mvnrepository.com/artifact/ junit
গ্রানাডা কোডার

v4.13 আর বিটা অবস্থায় নেই (জানুয়ারী 2020 এ প্রকাশিত)
সাইমন

11

প্রকৃতপক্ষে, চেষ্টা / ধরার মাধ্যমে সর্বোত্তম ব্যবহার। কেন? কারণ আপনি যেখানে ব্যতিক্রমটি প্রত্যাশা করছেন তা নিয়ন্ত্রণ করতে পারবেন।

এই উদাহরণ বিবেচনা করুন:

@Test (expected = RuntimeException.class)
public void someTest() {
   // test preparation
   // actual test
}

যদি একদিন কোডটি সংশোধিত হয় এবং পরীক্ষার প্রস্তুতিটি রানটাইম এক্সেকশন ফেলে দেয়? সেক্ষেত্রে প্রকৃত পরীক্ষা এমনকি পরীক্ষা করা হয় না এবং এমনকি যদি এটি কোনও ব্যতিক্রম না ফেলে তবে পরীক্ষাটি পাস হবে।

এজন্য টীকাতে নির্ভর করার চেয়ে চেষ্টা / ধরা ব্যবহার করা আরও ভাল।


দুঃখের বিষয়, এটিও আমার উত্তর।
শ্রীধর সারনোবাত

2
কোড পরিবর্তন সম্পর্কিত উদ্বেগগুলি ছোট, ক্রম-সুনির্দিষ্ট-সুনির্দিষ্ট পরীক্ষার কেস দ্বারা দূরীভূত হয়। কখনও কখনও এটি অনিবার্য হয় এবং আমাদের ক্যাচ / ট্রাই পদ্ধতিতে নির্ভর করতে হয়, তবে যদি এটি ঘন ঘন ঘটে থাকে তবে সম্ভাবনা হ'ল আমাদের পরীক্ষার কেস ফাংশনগুলি লেখার উপায়টি সংশোধন করা দরকার।
luis.espinal

এটি আপনার পরীক্ষা এবং / অথবা কোড নিয়ে সমস্যা। আপনি কোনও সাধারণ রানটাইম এক্সেকশন আশা করেন না, আপনি একটি নির্দিষ্ট ব্যতিক্রম বা খুব কমপক্ষে একটি নির্দিষ্ট বার্তা আশা করেন।
ডেনিস্ক

আমি RuntimeExceptionউদাহরণ হিসাবে ব্যবহার করেছি , এই ব্যতিক্রমটিকে অন্য কোনও ব্যতিক্রমের সাথে প্রতিস্থাপন করুন।
Krzysztof সিস্লো

8

রায়স্টর্মের একটি ভাল উত্তর ছিল। আমিও নিয়মের কোনও বড় অনুরাগী নই। আমি অনুরূপ কিছু করি, কেবলমাত্র পাঠযোগ্যতা এবং ব্যবহারযোগ্যতার জন্য আমি নিম্নলিখিত ইউটিলিটি ক্লাসটি তৈরি করি, যা প্রথম স্থানে টীকাগুলির একটি বড় প্লাস।

এই ইউটিলিটি ক্লাস যুক্ত করুন:

import org.junit.Assert;

public abstract class ExpectedRuntimeExceptionAsserter {

    private String expectedExceptionMessage;

    public ExpectedRuntimeExceptionAsserter(String expectedExceptionMessage) {
        this.expectedExceptionMessage = expectedExceptionMessage;
    }

    public final void run(){
        try{
            expectException();
            Assert.fail(String.format("Expected a RuntimeException '%s'", expectedExceptionMessage));
        } catch (RuntimeException e){
            Assert.assertEquals("RuntimeException caught, but unexpected message", expectedExceptionMessage, e.getMessage());
        }
    }

    protected abstract void expectException();

}

তারপরে আমার ইউনিট পরীক্ষার জন্য আমার কেবল কোডটি দরকার:

@Test
public void verifyAnonymousUserCantAccessPrivilegedResourceTest(){
    new ExpectedRuntimeExceptionAsserter("anonymous user can't access privileged resource"){
        @Override
        protected void expectException() {
            throw new RuntimeException("anonymous user can't access privileged resource");
        }
    }.run(); //passes test; expected exception is caught, and this @Test returns normally as "Passed"
}

2

যদি @ রুল ব্যবহার করে থাকেন তবে ব্যতিক্রম সেটটি টেস্ট ক্লাসের সমস্ত পরীক্ষার পদ্ধতিতে প্রয়োগ করা হয়।


2
জেসি মেরিম্যান প্রতিক্রিয়া ব্যবহার করে, ব্যতিক্রমটি কেবল পরীক্ষার পদ্ধতিগুলিতে যাচাই করা হয় যা প্রত্যাশিতএক্স.পেক্সট () এবং প্রত্যাশিত এক্স.এক্সপেক্টমেসেজ () এ কল করে। অন্যান্য পদ্ধতিগুলি প্রত্যাশিতEx = ExpectedException.none () সংজ্ঞাটি ব্যবহার করবে, এটি প্রত্যাশিত ব্যতিক্রম।
ডিম

2

জুনিতের সাথে ব্যাতিক্রম বলার উপায়টি আমি কখনই পছন্দ করি না। যদি আমি টীকাতে "প্রত্যাশিত" ব্যবহার করি তবে আমার দৃষ্টিকোণ থেকে মনে হচ্ছে আমরা "প্রদত্ত" যখন লঙ্ঘন করছি, তখন, "প্যাটার্ন কারণ" তখন "প্যাটার্নটি পরীক্ষার সংজ্ঞাটির শীর্ষে রাখা হয়েছে"।

এছাড়াও, যদি আমরা "@ বিধি" ব্যবহার করি তবে আমাদের এত বেশি বয়লারপ্লেট কোডটি মোকাবেলা করতে হবে। সুতরাং, আপনি যদি আপনার পরীক্ষার জন্য নতুন লাইব্রেরি ইনস্টল করতে পারেন তবে আমি AssertJ এ নজর দেওয়ার পরামর্শ দিই (সেই লাইব্রেরিটি এখন স্প্রিংবুট নিয়ে আসে)

তারপরে একটি পরীক্ষা যা "প্রদত্ত / যখন / তারপরে" নীতিগুলি লঙ্ঘন করে না এবং যাচাই করতে এটি AssertJ ব্যবহার করে করা হয়:

1 - ব্যতিক্রমটি আমরা প্রত্যাশা করছি। 2 - এটিতে একটি প্রত্যাশিত বার্তাও রয়েছে

এই মত চেহারা হবে:

 @Test
void should_throwIllegalUse_when_idNotGiven() {

    //when
    final Throwable raisedException = catchThrowable(() -> getUserDAO.byId(null));

    //then
    assertThat(raisedException).isInstanceOf(IllegalArgumentException.class)
            .hasMessageContaining("Id to fetch is mandatory");
}

1

আমি ব্যবহারকারীর 14৪১১১ এর উত্তর পছন্দ করি তবে এটি আরও সাধারণীকরণ হতে পারে। এখানে আমার গ্রহণ:

public abstract class ExpectedThrowableAsserter implements Runnable {

    private final Class<? extends Throwable> throwableClass;
    private final String expectedExceptionMessage;

    protected ExpectedThrowableAsserter(Class<? extends Throwable> throwableClass, String expectedExceptionMessage) {
        this.throwableClass = throwableClass;
        this.expectedExceptionMessage = expectedExceptionMessage;
    }

    public final void run() {
        try {
            expectException();
        } catch (Throwable e) {
            assertTrue(String.format("Caught unexpected %s", e.getClass().getSimpleName()), throwableClass.isInstance(e));
            assertEquals(String.format("%s caught, but unexpected message", throwableClass.getSimpleName()), expectedExceptionMessage, e.getMessage());
            return;
        }
        fail(String.format("Expected %s, but no exception was thrown.", throwableClass.getSimpleName()));
    }

    protected abstract void expectException();

}

নোট করুন যে "ব্যর্থ" স্টেটমেন্টটি চেষ্টা ব্লকের মধ্যে রেখে সম্পর্কিত দৃ as় ব্যতিক্রমটিকে ধরা পড়বে; ক্যাচ স্টেটমেন্টের মধ্যে রিটার্ন ব্যবহার করা এটি প্রতিরোধ করে।


0

ক্যাচ-ব্যতিক্রম পাঠাগারটি আমদানি করুন এবং এটি ব্যবহার করুন। এটি ExpectedExceptionবিধি বা ক এর চেয়ে অনেক বেশি পরিষ্কার try-catch

উদাহরণ তাদের দস্তাবেজগুলি গঠন:

import static com.googlecode.catchexception.CatchException.*;
import static com.googlecode.catchexception.apis.CatchExceptionHamcrestMatchers.*;

// given: an empty list
List myList = new ArrayList();

// when: we try to get the first element of the list
catchException(myList).get(1);

// then: we expect an IndexOutOfBoundsException with message "Index: 1, Size: 0"
assertThat(caughtException(),
  allOf(
    instanceOf(IndexOutOfBoundsException.class),
    hasMessage("Index: 1, Size: 0"),
    hasNoCause()
  )
);

-2
@Test (expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "This is not allowed")
public void testInvalidValidation() throws Exception{
     //test code
}

এই উত্তরটি -1 কেন কেউ আমাকে বুঝতে সাহায্য করতে পারে
আশাশা

প্রশ্নটি জিজ্ঞাসা করছে Junitতবে আপনি উত্তর দিচ্ছেনTestNG
হুয়াজে ইয়িন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.