@Override
  public Statement apply(final Statement base, final Description description) {
    return new Statement() {
      @Override
      public void evaluate() throws Throwable {
        try {
          base.evaluate();
        } catch (final Throwable e) {
          // Pay attention to the situation of MultipleFailureException...
          if ((e instanceof MultipleFailureException
                  && ((MultipleFailureException) e)
                      .getFailures().stream().allMatch(this::isExceptionInSetUpOrTearDown))
              || isExceptionInSetUpOrTearDown(e)) {
            Assume.assumeTrue(
                String.format(
                    "Skipping test due to setup or tearDown failure for %s#%s",
                    description.getClassName(), description.getMethodName()),
                false);
          }

          // Re-throw the exception (which means the test has failed).
          throw e;

          // Regardless of the circumstances, the method decorated with @After will always be
          // executed.
        }
      }

      private boolean isExceptionInSetUpOrTearDown(final Throwable e) {
        // Trace back the exception stack to determine whether the exception was thrown during the
        // setUp or tearDown phase.
        for (final StackTraceElement stackTraceElement : e.getStackTrace()) {
          if (setUpMethodName.equals(stackTraceElement.getMethodName())
              && description.getClassName().equals(stackTraceElement.getClassName())
              && isMethodAnnotationWithBefore(stackTraceElement.getMethodName())) {
            e.printStackTrace();
            return true;
          }

          if (tearDownMethodName.equals(stackTraceElement.getMethodName())
              && description.getClassName().equals(stackTraceElement.getClassName())
              && isMethodAnnotationWithAfter(stackTraceElement.getMethodName())) {
            e.printStackTrace();
            return true;
          }
        }
        return false;
      }

      private boolean isMethodAnnotationWithBefore(final String methodName) {
        try {
          final Method method = description.getTestClass().getDeclaredMethod(methodName);
          return method.isAnnotationPresent(org.junit.Before.class);
        } catch (final Throwable ignored) {
          return false;
        }
      }

      private boolean isMethodAnnotationWithAfter(final String methodName) {
        try {
          final Method method = description.getTestClass().getDeclaredMethod(methodName);
          return method.isAnnotationPresent(org.junit.After.class);
        } catch (final Throwable ignored) {
          return false;
        }
      }
    };
  }
@param setUpMethodName Should be exactly the same as the method name decorated with @Before.
@param tearDownMethodName Should be exactly the same as the method name decorated with @After.
integration-test/src/test/java/org/apache/iotdb/subscription/it/SkipOnSetUpAndTearDownFailure.java