Тестирование функции с использованием макета

#junit #mocking #mockito

#junit #издевательство #mockito

Вопрос:

Я хочу протестировать функцию, внутри которой есть вызов другой функции (которая принимает два параметра) Я хочу издеваться над этой внутренней функцией.Но у меня возникают трудности с тем, что передать в качестве параметра

 void func(classA a,classB b)
{
List<ClassC> list= Objd.func2(a.getSome(),b)
///some other things
}
  

теперь я хочу издеваться над этой func2 , у меня уже есть интерфейс для класса obj C.

Я попытался использовать

 InterfaceClassD objD=Mockito.mock(InterfaceClassD.class)
Mockito.when(obj.func2(a.getsome(),b)).thenreturn(null);
  

но это не работает, выполняется func2

Я даже пытался

 InterfaceClassD objD=Mockito.mock(InterfaceClassD.class)
Mockito.when(obj.func2(anyList(),any(classB.class)).thenreturn(null);
  

ПРИМЕЧАНИЕ — a.getSome() возвращает список
, но он тоже не работает, выполняется func2

Комментарии:

1. Является func2 ли статический метод в Objd классе?

2. нет, это не статический метод. вы можете рассматривать Objd как объект класса ClassD

Ответ №1:

Трудно ответить на этот вопрос без дополнительного контекста.

Откуда в функции «func» берется ссылка на «Objd»? Где она объявлена?

Создание и использование mocks в тесте состоит из двух этапов:

  1. создание макета
  2. внедрение макета

«Внедрение макета» относится к (каким-то образом) замене ссылки на реальный объект, который будет использовать функция, на макет версии, которую вы создали с помощью Mockito.

Пример:

 // Class under test
public class Foo {
  // this is the object we need to mock
  private InterfaceClassD objD;

  void func(classA a,classB b) {
    // here is where we use "objD"
    List<ClassC> list= objD.func2(a.getSome(),b)
    ///some other things
  }
}
  

Чтобы написать тест с макетом objD, вы должны заменить «реальный» objD на макет непосредственно перед вызовом тестируемого метода (функции).

Обычно это делается либо с помощью внедрения конструктора, либо с помощью установки, либо с помощью аннотаций Mockito.

Пример с внедрением конструктора:

 // Class under test
public class Foo {
  // this is the object we need to mock
  private InterfaceClassD objD;

  // constructor injection
  public Foo(InterfaceClassD objD) {
    this.objD = objD;
  }

  void func(classA a,classB b) {
    // here is where we use "objD"
    List<ClassC> list= objD.func2(a.getSome(),b);

    ///some other things
  }
}

// Unit test
public class FooTest {
  @Test
  public void someTest() {
    // create the mock:
    InterfaceClassD mock = Mockito.mock(InterfaceClassD.class);

    // inject the mock:
    Foo foo = new Foo(objD);

    // test: this should call method func but use the mock
    foo.func(dummyA, dummyB);

    // verify/assert something...
  }
}
  

Пример использования внедрения установщика:

 // Class under test
public class Foo {
  // this is the object we need to mock
  private InterfaceClassD objD;

  // setter injection
  public void setInterfaceClassD(InterfaceClassD objD) {
    this.objD = objD;
  }

  void func(classA a,classB b) {
    // here is where we use "objD"
    List<ClassC> list= objD.func2(a.getSome(),b);

    ///some other things
  }
}

// Unit test
public class FooTest {
  @Test
  public void someTest() {
    // create the mock:
    InterfaceClassD mock = Mockito.mock(InterfaceClassD.class);

    Foo foo = new Foo();
    // inject the mock:
    foo.setInterfaceClassD(mock);

    // test: this should call method func but use the mock
    foo.func(dummyA, dummyB);

    // verify/assert something...
  }
}
  

Пример использования аннотаций Mockito и JUnit 5:

 // Class under test
public class Foo {
  // this is the object we need to mock
  private InterfaceClassD objD;

  void func(classA a,classB b) {
    // here is where we use "objD"
    List<ClassC> list= objD.func2(a.getSome(),b);

    ///some other things
  }
}

// Unit test
// Note the Mockito extension annotation.
@ExtendWith(MockitoExtension.class)
public class FooTest {
  // the Mockito JUnit extension will instantiate this automagically.
  // The name of the mock must exactly match the name of the field in
  // containing class.
  private @Mock InterfaceClassD objD;

  // Mockito annotation processing will create an instance of Foo, and
  // replace any of its fields with any mocks that have the same name
  // and type. In this case, objD.
  private @InjectMocks Foo foo;

  @Test
  public void someTest() {
    // Just use it.
    // test: this should call method func but use the mock
    foo.func(dummyA, dummyB);

    // verify/assert something...
  }
}