Подтвердить что ты не робот

Макет частного статического конечного поля с использованием mockito или Jmockit

Я использую поле private static final LOGGER в моем классе, и мне нужно метод LOGGER.isInfoEnabled() вернуть false. Как я могу высмеять статическое конечное поле с помощью mockito или jMockit

Мой класс:

  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;

  public class Class1 {

  private static final Logger LOGGER = LoggerFactory.getLogger(Class1.class);

    public boolean demoMethod() {
       System.out.println("Demo started");
       if (LOGGER.isInfoEnabled()) {
         System.out.println("@@@@@@@@@@@@@@ ------- info is enabled");
       } else {
         System.out.println("info is disabled");
       }
       return LOGGER.isInfoEnabled();
    }
  }

и его юнит:

import mockit.Mocked;
import mockit.NonStrictExpectations;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import static org.testng.Assert.*;
import com.source.Class1;

public class MyTest {

  @InjectMocks
  Class1 cls1;

  @BeforeMethod
  public void initMocks() {
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void test(@Mocked final Logger LOGGER) {

    new NonStrictExpectations() {
      {
        LOGGER.isInfoEnabled();
        result = false;
      }
    };
    assertFalse(cls1.demoMethod());
  }
}

когда я запускаю его, результат:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.test.MyTest
Configuring TestNG with: TestNG652Configurator
Demo started
@@@@@@@@@@@@@@ ------- info is enabled
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.9 sec <<< FAILURE! - in com.test.MyTest
test(com.test.MyTest)  Time elapsed: 0.168 sec  <<< FAILURE!
java.lang.AssertionError: expected [false] but found [true]
        at com.test.MyTest.test(MyTest.java:35)


Results :

Failed tests:
  MyTest.test:35 expected [false] but found [true]

Tests run: 1, Failures: 1, Errors: 0, Skipped: 0

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 9.899s
[INFO] Finished at: Mon Jun 08 12:35:36 IST 2015
[INFO] Final Memory: 16M/166M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.18.1:test (default-test) on project JMockDemo: The
re are test failures.
[ERROR]
[ERROR] Please refer to D:\perfoce_code\workspace_kepler\JMockDemo\target\surefire-reports for the individual test results.
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Я новичок в jmockit, и я хочу, чтобы мой предыдущий случай junit работал успешно. И я должен использовать JMockit или mockito, не могу использовать Powermockito. Пожалуйста, помогите.

4b9b3361

Ответ 1

Один из способов - использовать отражение, избавляющееся от модификатора final от поля, а затем заменить поле LOGGER на Mocked one

public class Class1Test {
    @Test
    public void test() throws Exception {
        Logger logger = Mockito.mock(Logger.class);
        Mockito.when(logger.isInfoEnabled()).thenReturn(false);
        setFinalStatic(Class1.class.getDeclaredField("LOGGER"), logger);
        Class1 cls1 = new Class1();
        assertFalse(cls1.demoMethod());
    }

    static void setFinalStatic(Field field, Object newValue) throws Exception {
        field.setAccessible(true);        
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }
}

Ответ 2

Я думаю, что mockito или jMockit не могут издеваться над статическими конечными классами, поскольку они пытаются переопределить методы во время модульного тестирования. Однако powerMockito может использовать Reflection и издевается над статическим окончательным классом/методами.

Ответ 3

Если в параметре изменить "@Mocked Logger" на "@Capturing Logger", это сработает. лайк

  @Test
  public void test(@Capturing final Logger LOGGER) {

    new NonStrictExpectations() {
      {
        LOGGER.isInfoEnabled();
        result = false;
      }
    };
    assertFalse(cls1.demoMethod());
  }