как издеваться над вызовом метода, который не выполняется какой-либо зависимостью класса? - PullRequest
1 голос
/ 07 мая 2020

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

class C{
    public C fun(D d){
       // fetch some data from database using object of D
       // do some operations on that data 
       // create an object of C using this data
       // return that object of C
    }
 }
@Component
class toBeTested{
   @Autowired private A a;
   @Autowired private B b;
   public C methodToBeTested(){
        C c = new C(a.getD()).fun();
        return c;
   } 
}

Я хочу протестировать метод methodToBeTested (). Скажите, есть ли способ имитировать вызовы метода объекта D, присутствующего в классе C, во время выполнения метода fun (). Или есть другой простой способ справиться с этой ситуацией в mockito. Все, что я нашел до сих пор, это Переполнение стека , но все же я не понимаю, как использовать это в моей ситуации

Ответы [ 2 ]

2 голосов
/ 07 мая 2020

Если вы используете @Autowired в классе C, этот C должен управляться Spring, иначе "autowiring magi c D внутри C не произойдет"

Но если да, то зачем вы создаете новый экземпляр C в классе toBeTested? На самом деле это не имеет смысла.

Итак, вам следует:

  1. Поместить @Component в класс C, чтобы Spring справился с этим.
  2. Изменить class toBeTested:
@Component
class toBeTested{
   @Autowired private A a;
   @Autowired private B b;
   @Autowired private C c; 
   public C methodToBeTested(){
        return c.fun();
   } 
}

Довольно странно видеть c .fun (), который возвращает сам себя, это строитель или что-то в этом роде? Возможно, вам стоит сделать его «прототипом», и тогда решение будет немного другим, но, поскольку оно не упомянуто в вопросе, у меня недостаточно деталей, поэтому я оставлю ответ как есть ...

Обновление 1

Теперь, когда ясно, что класс C по причинам, не зависящим от OP, не управляется Spring, есть два варианта:

  1. Используйте PowerMock / Power Mockito, если вам нужно сохранить класс toBeTested в его текущей форме (с new C() in the method to be tested. Этот подход в целом считается плохой практикой, используйте его только в том случае, если у вас нет другого выбора. Эти инструменты могут имитировать создание объекта (новый) и заменять C какой-нибудь заглушкой на лету.

  2. Если вы можете изменить класс toBeTested - используйте инъекцию зависимостей:

public class ToBeTested {
   @Autowired private A a;
   @Autowired private B b;
   @Autowired private CFactory cFactory; 

   public C methodToBeTested() {
      return cFactory.create(a.getD()).fun();
   }  
}

interface CFactory {
    C create(D d);
}

@Component
public class DefaultCFactoryImpl implements CFactory {
   public C createC(D d) {
      return new C(d);
   }
}

Этот подход намного лучше, поскольку он позволяет заменить фабрику реализацией, которая создаст имитацию C или того, что вы сочтете подходящим для теста.

0 голосов
/ 07 мая 2020

Всегда лучше использовать инъекцию конструктора.

Но если вы не хотите проводить рефакторинг, вы можете использовать @InjectMocks из mockito.

class ToBeTestedTest {
   @Mock private A a;
   @Mock private B b;
   @InjectMocks ToBeTested toBeTested; // mockito will inject your mocks

   @Before
   public void setUpMocks() {
      when(a.getSomeParameter()).thenReturn(new DummyObject())
   }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...