Является ли использование метода класса Logger решением этой ошибки org / apache / commons / logging / LogFactory java .lang.NoClassDefFoundError? - PullRequest
0 голосов
/ 30 апреля 2020

Я написал тест для класса, в котором я использую Apache logger, поэтому я создал Custom Logger, как упомянуто ниже.

 import java.io.Externalizable;
    import java.io.IOException;
    import java.io.ObjectInput;
    import java.io.ObjectOutput;
    import java.io.Serializable;

    import java.sql.SQLException;

    import com.medicalis.platform.InternalPlatformException;
    import com.medicalis.platform.MedicalisException;
    import com.medicalis.platform.MedicalisSQLException;
    import com.medicalis.platform.logging.windows.LogSeverity;
    import com.medicalis.platform.logging.windows.WindowsLoggingUtils;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;

    public class Logger implements Serializable, Externalizable {
       private Log myLogger = null;
       private String categoryName = null;
       private static final int DEFAULT_EVENT_ID = 9;
       private static final String SQL_STATE_CONSTRAINT_ERROR = "23000";

       /**
        * Creates a new Logger object.
        */
       public Logger() {
       }

       /**
        * Write objects member variables to object stream
        *
        * @param out - ObjectOutput
        *
        * @throws IOException
        */
       public void writeExternal(ObjectOutput out)
          throws IOException {
          out.writeObject(categoryName);
       }

       /**
        * Reads object stream to reconstruct object's member variables
        *
        * @param in - ObjectInput
        *
        * @throws IOException
        * @throws ClassNotFoundException
        */
       public void readExternal(ObjectInput in)
          throws IOException, ClassNotFoundException {
          this.categoryName = (String) in.readObject();
          this.myLogger = LogFactory.getLog(this.categoryName);
       }

       /**
        * Initializes log factory used for all logging.
        *
        * @param log - base logger
        * @param categoryName - String name of logger category
        */
       private Logger(Log log, String categoryName) {
          this.categoryName = categoryName;
          myLogger = log;
       }

       /**
        * Returns a Category instance for the given category name.
        *
        * @param categoryName - String name to use as the name for the log category
        *
        * @return Category logger object
        */
       public static Logger getInstance(final String categoryName) {
          Log log = LogFactory.getLog(categoryName);
          Logger logger = new Logger(log, categoryName);

          return logger;
       }

       /**
        * Returns a Category instance for the given category name.
        *
        * @param categoryClass - Object whose fully qualified classname will be used to determine the
        *        log category
        *
        * @return Category logger object
        */
       public static Logger getInstance(final Class categoryClass) {
          return getInstance(categoryClass.getName().toString());
       }

       /**
        * Logs a message at trace priority.
        *
        * @param obj object whose toString() method is used to get the message to log
        */
       public void trace(Object obj) {
          this.trace((obj == null) ? "null" : obj.toString(), null);
       }

       /**
        * Logs a message at debug priority.
        *
        * @param msg message to log
        * @param t object describing the exception or error that needs to be logged
        */
       public void trace(String msg, Throwable t) {
          myLogger.trace(msg, t);
       }

       /**
        * Logs a message at debug priority.
        *
        * @param obj object whose toString() method is used to get the message to log
        */
       public void debug(Object obj) {
          this.debug((obj == null) ? "null" : obj.toString(), null);
       }

       /**
        * Logs a message at debug priority.
        *
        * @param msg message to log
        * @param t object describing the exception or error that needs to be logged
        */
       public void debug(String msg, Throwable t) {
          myLogger.debug(msg, t);
       }

       /**
        * Logs a message at info priority.
        *
        * @param obj object whose toString() method is used to get the message to log
        */
       public void info(Object obj) {
          this.info((obj == null) ? "null" : obj.toString(), null);
       }

       /**
        * Logs a message at info priority.
        *
        * @param msg message to log
        * @param t object describing the exception or error that needs to be logged
        */
       public void info(String msg, Throwable t) {
          myLogger.info(msg, t);
       }

       /**
        * Logs a message at warn priority.
        *
        * @param obj object whose toString() method is used to get the message to log
        */
       public void warn(Object obj) {
          this.warn((obj == null) ? "null" : obj.toString(), null);
       }

       /**
        * Logs a message at warn priority.
        *
        * @param msg message to log
        * @param t object describing the exception or error that needs to be logged
        */
       public void warn(String msg, Throwable t) {
          myLogger.warn(msg, t);

          if (myLogger.isWarnEnabled()) {
             if (t instanceof MedicalisException) {
                WindowsLoggingUtils.log((MedicalisException) t, LogSeverity.WARNING);
             } else if (t == null) {
                WindowsLoggingUtils.log(msg, DEFAULT_EVENT_ID, LogSeverity.WARNING);
             }
          }
       }

       /**
        * Logs a message at error priority.
        *
        * @param obj object whose toString() method is used to get the message to log
        */
       public void error(Object obj) {
          this.error((obj == null) ? "null" : obj.toString(), null);
       }

       /**
        * Logs a message at error priority.
        *
        * @param msg message to log
        * @param t object describing the exception or error that needs to be logged
        */
       public void error(String msg, Throwable t) {
          myLogger.error(msg, t);

          if (myLogger.isErrorEnabled() && t instanceof MedicalisException) {
             if (!isSQLConstraintError(t)) {
                WindowsLoggingUtils.log((MedicalisException) t, LogSeverity.ERROR);
             }
          }
       }

       /**
        * Returns whether or not trace logging is enabled.
        *
        * @return boolean indicating if trace logging is enabled (true).
        */
       public boolean isTraceEnabled() {
          return myLogger.isTraceEnabled();
       }

       /**
        * Returns whether or not debug logging is enabled.
        *
        * @return boolean indicating if debug logging is enabled (true).
        */
       public boolean isDebugEnabled() {
          boolean isDebug = false;

          isDebug = myLogger.isDebugEnabled();

          if (!isDebug) {
             isDebug = Boolean.getBoolean("system.debug.on");
          }

          return isDebug;
       }

       /**
        * Returns whether or not info logging is enabled.
        *
        * @return boolean indicating if info logging is enabled (true).
        */
       public boolean isInfoEnabled() {
          return myLogger.isInfoEnabled();
       }

       /**
        * Returns whether or not warn logging is enabled.
        *
        * @return boolean indicating if warn logging is enabled (true).
        */
       public boolean isWarnEnabled() {
          return myLogger.isWarnEnabled();
       }

       /**
        * Returns whether or not error logging is enabled.
        *
        * @return boolean indicating if error logging is enabled (true).
        */
       public boolean isErrorEnabled() {
          return myLogger.isErrorEnabled();
       }

       /**
        * Method to determine if the error being thrown is the
        * result of a SQLConstraint Error. (This type of error may be logged
        * differently).
        *
        * @param t Throwable
        *
        * @return boolean
        */
       public boolean isSQLConstraintError(Throwable t) {
          boolean isContraintErr = false;

          Throwable cause = t;

          while (cause != null) {
             if (cause instanceof SQLException) {
                SQLException sqlCause = (SQLException) cause;

                String sqlState = sqlCause.getSQLState();

                if ((sqlState != null) && sqlState.equals(SQL_STATE_CONSTRAINT_ERROR)) {
                   isContraintErr = true;
                }

                break;
             }

             // check for infinite nesting of exceptions
             Throwable lastCause = cause;

             cause = cause.getCause();

             if (cause == lastCause) {
                break;
             }
          }

          return isContraintErr;
       }
    }

Я использую этот регистратор в моем классе, как упоминается ниже.

 private static final Logger log = Logger.getInstance(TimeZoneUtil.class);

Если в моей тестовой сборке я включаю зависимость общего типа - apache -logger-аналог, как упомянуто ниже, поэтому я не получаю никакой ошибки под названием java .lang.NoClassDefFoundError: org / apache / commons / logging / LogFactory

<fileset dir="./../thirdparty/commons-logging-1.1.1">
         <include name="*.jar" />
      </fileset>

Но я не хочу использовать это включение jar в моей тестовой сборке, так что есть какой-то другой подход к макету метода getInstance (), поэтому он не должен входить внутри класса logger для создания журнала или любого другого способа избавиться от этой ошибки.

В настоящее время я использую Power Mockito, как упомянуто ниже, с помощью которого я могу издеваться над классом Logger, но даже после этого я Получение ошибки.

      PowerMockito.mockStatic(Logger.class);
      Logger logger = mock(Logger.class);
      when(Logger.getInstance(TimeZoneUtil.class)).thenReturn(logger);
      when(Logger.getInstance(any(String.class))).thenReturn(logger);

Ошибка:

Testsuite: com.medicalis.platform.timing.TimeZoneUtilTest
Tests run: 0, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.033 sec

Testcase: com.medicalis.platform.timing.TimeZoneUtilTest took 0 sec
    Caused an ERROR
org/apache/commons/logging/LogFactory
java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
    at com.medicalis.platform.logging.Logger.getInstance(Logger.java:107)
    at com.medicalis.platform.logging.Logger.getInstance(Logger.java:122)
    at com.medicalis.platform.timing.TimeZoneUtil.<clinit>(TimeZoneUtil.java:30)
    at com.medicalis.platform.timing.KnownTimeZone.loadValuesImpl(KnownTimeZone.java:51)
    at com.medicalis.platform.timing.TimeZoneUtilTest.setUp(TimeZoneUtilTest.java:69)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
    at java.lang.ClassLoader.loadClass(ClassLoader.java:352)

Пожалуйста, помогите мне, предложив хороший подход, чтобы я не получал эту ошибку, это может быть насмешкой над объектом, издевающимся над мето d или любой другой подход, который может решить эту проблему, за исключением предоставления зависимости в тестовой сборке, заранее спасибо.

Включая ниже отправную точку моего класса проверенного тестового случая.

//import static org.easymock.EasyMock.mock;
import static org.junit.Assert.*;

import java.sql.SQLException;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.sql.RowSet;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.powermock.api.mockito.PowerMockito.*;

import static org.mockito.Matchers.*;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
//import static org.easymock.EasyMock.expect;
import com.medicalis.common.shared.UUIDHelper;
import com.medicalis.platform.logging.Logger;
import com.medicalis.platform.user.valueobject.UserData;
//import static org.powermock.api.easymock.PowerMock.mockStatic;

@RunWith(PowerMockRunner.class)
@PrepareForTest({Logger.class, LogFactory.class, TimeZoneUtil.class, KnownTimeZone.class})
public class TimeZoneUtilTest {
   public static final String UNIT_TEST_PROPERTY = "timeZoneUtilsUnitTestRunning";
   private static final String EUCLA_TZ = "Australia/Eucla";
   private static final String LA_TZ = "America/Los_Angeles";
   private static final String PERTH_TZ = "Australia/Perth";
   private static final String AUSTRALIA_PERTH_SHORT_CD = "APER";
   private static final String PERTH_TZ_JSON = "[{'timeZoneCd': 'APER', 'javaId': 'Australia/Perth', 'displayCode': 'AWST', 'timeZoneId': 12, 'windowsId': '(UTC+08:00) Perth'}]";

   private static List javaIdTestValue, timeZonesTestValue;
   private static UserData professionalUserData, rmUserData;

   /*package*/ static boolean isUnitTestRunning() {
      return String.valueOf(true).equals(System.getProperty(TimeZoneUtilTest.UNIT_TEST_PROPERTY));
   }

   @BeforeClass
   public static void setUp() throws SQLException, JSONException {

     /* mockStatic(LogFactory.class);
      Log log = mock(Log.class);
      when(LogFactory.getLog(anyString())).thenReturn(log);
   */

     mockStatic(Logger.class);
      Logger logger = mock(Logger.class);
     // expect(Logger.getInstance(TimeZoneUtil.class)).andReturn(logger);

     when(Logger.getInstance(TimeZoneUtil.class)).thenReturn(logger);
      when(Logger.getInstance(any(String.class))).thenReturn(logger);

      when(logger.isDebugEnabled()).thenReturn(Boolean.valueOf("true"));

      doNothing().when(logger).error(anyString(),any());
      doNothing().when(logger).warn(anyString(),any());

      doNothing().when(logger).debug(anyString(),any());

     doNothing().when(logger).error(anyString(),any());
      System.setProperty(UNIT_TEST_PROPERTY, String.valueOf(true));

      RowSet rowSet = new TimeZoneUtilTestRowSet();
      rowSet.next();
      rowSet.setString("javaId", EUCLA_TZ);
      javaIdTestValue = Collections.singletonList(rowSet);

      RowSet timeZoneRowSet = new TimeZoneUtilTestRowSet(new JSONArray(PERTH_TZ_JSON));
      timeZonesTestValue = Collections.singletonList(timeZoneRowSet);
      KnownTimeZone.loadValuesImpl(timeZonesTestValue);

      professionalUserData = new UserData() {
         @Override
         public boolean isProfessionalContext() {
            return true;
         }

         @Override
         public String getProfessionalTimeZoneId() {
            return LA_TZ;
         }
      };
      professionalUserData.setPreferredTimeZone(AUSTRALIA_PERTH_SHORT_CD);

      rmUserData = new UserData();
      rmUserData.setPreferredTimeZone(AUSTRALIA_PERTH_SHORT_CD);
   }

Ответы [ 2 ]

0 голосов
/ 30 апреля 2020

вы можете написать свой тест, как это ...

public class TimeZoneUtilTest {
   public static final String UNIT_TEST_PROPERTY = "timeZoneUtilsUnitTestRunning";
   private static final String EUCLA_TZ = "Australia/Eucla";
   private static final String LA_TZ = "America/Los_Angeles";
   private static final String PERTH_TZ = "Australia/Perth";
   private static final String AUSTRALIA_PERTH_SHORT_CD = "APER";
   private static final String PERTH_TZ_JSON = "[{'timeZoneCd': 'APER', 'javaId': 'Australia/Perth', 'displayCode': 'AWST', 'timeZoneId': 12, 'windowsId': '(UTC+08:00) Perth'}]";

   private static List javaIdTestValue, timeZonesTestValue;
   private static UserData professionalUserData, rmUserData;

    @Mock
    Logger logger;
    //....
   }


0 голосов
/ 30 апреля 2020

В перед попыткой смоделировать stati c метод как:

   @Before
   public void before() throws Exception {
      mockStatic(LogFactory.class);
      Log log = mock(Log.class);
      when(LogFactory.getLog(anyString())).thenReturn(log);
      when(LogFactory.getLog(any(Class.class))).thenReturn(log);
   }

или

   @Before
   public void before() throws Exception {
     mockStatic(Logger.class);
     Logger logger = mock(Logger.class);
     when(Logger.getInstance(any())).thenReturn(logger);
   }
...