Squeak.ru - шаблоны программирования

Насмешка над конструктором, который дает ссылку на базовый класс с использованием Powermockito в java

Вот сценарий, у меня есть что-то подобное в одном из моих методов класса MyClass

public class MyClass{

    public Object build(Map map) {

        BaseClass cls;     

        if(SomeconditionTrue) {

         cls = new ChildClass1(new ABC());

        } else {

        cls = new ChildClass2(new ABC());

       }

       cls.callMethod();

    }

}

Для приведенного выше сценария я пишу тестовый пример с использованием PowerMockito, я хочу издеваться над этим вызовом метода, cls.callMethod(). Когда я пытаюсь издеваться, он вызывает фактический метод callMethod(), который терпит неудачу. Может ли кто-нибудь помочь мне издеваться над этим вызовом метода? Пробовал использовать пару сценариев, используя PowerMockito PowerMockito.stub и некоторые другие параметры, но он всегда вызывает фактический метод. Причина, по которой мы имитируем этот метод, заключается в том, что он имеет другую логику и вызывает разные API, метод довольно сложный, поэтому нам нужно имитировать этот метод.


Ответы:


1

Для этого вы можете обратиться к Powermock, но это не обязательно «лучший» ответ на такие проблемы.

По сути, тот факт, что вы вызываете new в своем коде, вызывает у вас огорчение — этим вы создали трудно тестируемый код. Вы можете посмотреть эти видео, чтобы понять, о чем я говорю.

Короче говоря: вместо того, чтобы обращаться к большому молотку Powermock, вы могли бы вместо этого переработать свой код; использовать внедрение зависимостей. Таким образом, вместо того, чтобы создавать эти объекты самостоятельно, ваш тестируемый класс может использовать какой-либо фабричный объект для предоставления необходимого ему объекта. И затем вы можете использовать любой «обычный» макетный фреймворк, такой как EasyMock или Mockito, чтобы создать издевательскую версию этой фабрики.

Изменить: я думаю, вы, возможно, слишком усложнили всю проблему. Видите ли, на самом деле не имеет значения, есть ли базовый класс или два дочерних класса. Дело в том, что для каждого из ваших тестовых методов вы должны точно понимать, по какому пути пойдете. Вы либо хочете, чтобы был создан дочерний элемент1, либо дочерний элемент. Таким образом, я создал для вас упрощенное решение:

package ghostcat.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

class Abc {}

abstract class Base {
  void callMethod() {
    System.out.println("Base::callMethod");
  }
}

class ChildClass1 extends Base {
  ChildClass1(Abc abc) {}
}

class MyClass {
  public Object build() {
    System.out.println("build1");
    Base cls = new ChildClass1(new Abc());
    System.out.println("build2");
    cls.callMethod();
    System.out.println("build3");
    return null;
  } 
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyClass.class)
public class MockNewTest {
  @Test
  public void test() throws Exception {
    ChildClass1 mock = Mockito.mock(ChildClass1.class);
PowerMockito.whenNew(ChildClass1.class).withArguments(Mockito.any(Abc.class)).thenReturn(mock);
    new MyClass().build();
}

}

Отпечатки:

build1
build2
build3

Вот видите - ничего в базе не вызывается; просто потому, что этот дочерний объект "полностью" издевался.

Суть в том, что для вашего тестируемого кода просто требуется один объект определенного типа; и вы заранее знаете, будет ли это ребенок1 или ребенок2. Итак, вы просто создаете макет для этого класса; и используйте PowerMockito, чтобы вернуть тот макет, который вы только что создали.

Для протокола: некоторое время я играл со шпионами; но они не помогают здесь; и они тоже не обязательны!

15.12.2016
  • Спасибо за ответ. Да, мы можем использовать какой-нибудь фабричный шаблон, но тестовый пример, который я пишу, предназначен для устаревшего кода, мы не хотим трогать существующий код. Есть ли альтернативный вариант, кроме изменения существующего кода? 15.12.2016
  • @ user2334926 Я обновил свой ответ; вытащил полный пример, который сработал для меня. 15.12.2016
  • Новые материалы

    API следующего поколения: gRPC n Javascript
    gRPC - быстро развивающаяся технология, которая потенциально может заменить протокол HTTP. Это быстрее, чем традиционные HTTP-вызовы, потому что он отправляет данные в двоичном формате, а не в..

    Ускоренный курс по жадным алгоритмам
    Дай мне, дай мне, дай мне Аудитория Эта статья предназначена для инженеров, достаточно хорошо разбирающихся в программировании, структурах данных и алгоритмах. Он в основном основан на..

    Изучайте Java (Урок 2: Комментарии)
    Как и зачем использовать комментарии в java с примерами Введение: Комментарии — это строки текста в программе Java, которые игнорируются компилятором и используются для добавления..

    Async Await в Swift: легкое управление параллелизмом
    Введение в запуск асинхронного кода Асинхронный код выполняет несколько операций одновременно. Параллелизм необходим при выполнении тяжелых вычислений или сетевых запросов. Однако это может..

    Очистить файлы Program .cache в Ubuntu 20.10
    Очистите кеш за несколько простых шагов! GNU / Linux реализовал эффективное управление хранилищем для своих пользователей. Но заметили ли вы, что в вашей системе Linux заканчивается место,..

    Использование Node.js для чтения действительно больших файлов (часть 1)
    В этом сообщении в блоге есть интересный источник вдохновения. На прошлой неделе кто-то на одном из моих каналов в Slack опубликовал тестовое задание, которое он получил на должность..

    Введение в градиентный спуск и обратное распространение
    Введение в градиентный спуск и обратное распространение Как машинное обучение? Машинное обучение ( ML ) - это исследование компьютерных алгоритмов, которые автоматически улучшаются по..