Метод класса Mocking System с использованием testng, mockito и powermock

В настоящее время я пишу тесты в устаревший код, который использует функцию System.getenv("some_environment_variable")

У меня возникает проблема, когда я пытаюсь смоделировать эти переменные, используя mockito и powermock (используется в рамках testng framework)

То, что я сделал до сих пор, было

@BeforeClass
public void setup() {
    PowerMockito.mockStatic(System.class);
    PowerMockito.when(System.getenv("hello")).thenReturn("world");
}

@Test
public void test() {
    assertEquals(System.getenv("hello"), "world");
}

Но когда я попытался запустить приведенный выше код, я получил следующую ошибку:

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() требует аргумент, который должен быть "вызовом метода для макета". Например: when(mock.getArticles()). ThenReturn(Articles);

Кроме того, эта ошибка может появиться, потому что:

  1. Вы заглушаете любой из методов: final/private/equals()/hashCode(). Эти методы не могут быть проверены. Методы насмешек, объявленные в закрытых родительских классах, не поддерживаются.

  2. внутри when() вы вызываете метод не на mock, а на каком-то другом объекте.

Итак, я прочитал и увидел, что эта ошибка возникает при попытке смоделировать метод с помощью насмешки над самим классом, но здесь это не так.

2 ответа

Решение

Поработав с этим довольно долго, вот как мне удалось это сделать.

В двух словах, чтобы заставить powermockito и TestNG работать друг с другом, вы должны сделать следующее (цитата из поста в блоге, ссылка которого приведена ниже, так что ответ будет полным и будет полезен, даже если блог недоступен в более поздний момент времени)

  1. Сконфигурируйте TestNG для использования фабрики объектов PowerMock: это можно сделать либо с помощью атрибута object-factory в вашем <suite> тег вашего набора XML или через @org.testng.annotations.ObjectFactory аннотированный метод, который возвращает реализацию PowerNock интерфейса TestNG org.testng.IObjectFactory а именно, org.powermock.modules.testng.PowerMockObjectFactory (или) путем расширения org.powermock.modules.testng.PowerMockTestCase

  2. использование @PrepareForTest подготовить статический класс к тому, чтобы его высмеивали PowerMockito

Пожалуйста, обратитесь к этому блогу для более подробной информации.

Вот рабочий образец:

import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

@PrepareForTest(System.class)
public class SampleTestClass {
    @BeforeClass
    public void setup() {
        PowerMockito.mockStatic(System.class);
        PowerMockito.when(System.getenv("hello")).thenReturn("world");
    }

    @Test
    public void test() {
        assertEquals(System.getenv("hello"), "world");
    }

    @ObjectFactory
    public IObjectFactory getObjectFactory() {
        return new org.powermock.modules.testng.PowerMockObjectFactory();
    }

}

Я использовал следующие зависимости для создания этого образца

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-testng</artifactId>
    <version>1.7.0</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.7.0</version>
    <scope>test</scope>
</dependency>

Есть еще одна библиотека JUnit, которая может вам помочь: системные правила, которые позволят вам, среди прочего, устанавливать и восстанавливать переменные среды. Используется совместно с JUnit @Rules

Другие вопросы по тегам