Как сделать JMockIt System.getenv (String)? - PullRequest
5 голосов
/ 27 октября 2009

Что у меня сейчас

У меня есть сторонний экземпляр синглтона, на который опирается мой тестируемый класс, и этот синглтон использует System.getenv(String) в своем конструкторе. Можно ли издеваться над этим звонком?

Я пробовал это

Пример JMockIt

    new Expectations()
    {

        System mockedSystem;
        {
            System.getenv( "FISSK_CONFIG_HOME" ); returns( "." );
        }
    };

Но это дает мне EXCEPTION_ACCESS_VIOLATION и приводит к сбою JVM.

Есть ли другой способ установить системную переменную среды для модульного теста?

Ответы [ 5 ]

15 голосов
/ 30 октября 2009

В этом случае вам нужно использовать частичное моделирование, чтобы JMockit не переопределял все в классе System. Следующий тест пройдет:

   @Test
   public void mockSystemGetenvMethod()
   {
      new Expectations()
      {
         @Mocked("getenv") System mockedSystem;

         {
            System.getenv("envVar"); returns(".");
         }
      };

      assertEquals(".", System.getenv("envVar"));
   }

Скоро я добавлю усовершенствование, чтобы подобные проблемы не возникали при насмешках над классами JRE. Он должен быть доступен в версии 0.992 или 0.993.

3 голосов
/ 27 октября 2009

PowerMock швы для возможности моделирования системных классов.

Другой вариант (при условии, что вы не проводите модульное тестирование стороннего API) - это создать для Фасад сторонний API, который имеет приятный и легко поддающийся моделированию интерфейс, и ваши тестовые классы используют его скорее чем настоящая вещь.

О, JMock также поддерживает это: пакетный тест;

import static org.junit.Assert.*;

import mockit.*;
import mockit.integration.junit4.JMockit;

import org.junit.*;
import org.junit.runner.RunWith;

@RunWith(JMockit.class)
public class JMockItTest {

 @Test
 public void mockSystemGetEnv() {
  Mockit.setUpMocks(MockSystem.class); 

  assertEquals("Bye", System.getenv("Hello"));

 }

 @MockClass(realClass = System.class)
 public static class MockSystem {
  @Mock
  public static String getenv(String str) {
   return "Bye";
  }
 }

}
2 голосов
/ 27 октября 2009

Вы не можете изменить среду, но вы можете изменить доступ к ней: просто оберните вызов System.getenv() в метод или вспомогательный класс, а затем смоделируйте это.

[РЕДАКТИРОВАТЬ] Теперь ваша проблема заключается в том, как изменить код вашей сторонней библиотеки. Решением здесь является использование декомпилятора Java и исправление класса. Если вы хотите, вы можете отправить запрос на функцию в тоже. Добавьте этот новый класс в ваш набор тестов. Это должно заставить вашу IDE найти класс для тестов.

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

1 голос
/ 27 октября 2009

Некоторое время назад я хотел протестировать System.exit и нашел решение с помощью пользовательского SecurityManager . Вы можете убедиться в том, что выполняется вызов, и в качестве аргумента вызова, но, используя этот метод, вы не можете высмеять возвращаемое значение вызова.

0 голосов
/ 12 августа 2016

Обновление @ Rogério answer.

В моем случае с JMockit 1.25 мне пришлось сделать это с помощью MockUp API:

@Test
public void mockSystemGetenvMethod(){
    new MockUp<System>()
    {
        @Mock
        public String getenv(final String string) {
            return "";
        }
    };

    assertEquals(".", System.getenv("envVar"));
}
...