Подтвердить что ты не робот

Модуль тестирует класс с автоподзаводом с помощью Junit и EasyMock?

Я пытаюсь написать Unit test для класса, у которого есть несколько полей, помеченных @Autowired. Учитывая, что Spring автоматически разрешает конкретные реализации для этих полей, мне сложно определить, как подключить мои объекты Mock (созданные через EasyMock) в качестве зависимостей во время тестового запуска. Использование @Autowired в классе означает отсутствие сеттеров в этом классе. Есть ли способ для меня подключить мои макетные объекты, не создавая дополнительных настроек в классе?

Вот пример того, что я пытаюсь выполнить:

public class SomeClassUnderTest implements SomeOtherClass{

@Autowired
private SomeType someType;

@Autowired
private SomeOtherType someOtherType;

@Override
public SomeReturnType someMethodIWouldLikeToTest(){
//Uses someType and someOtherType and returns SomeReturnType
}

}

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

public class MyTestClassForSomeClassUnderTest{
  private SomeType someType;
  private SomeOtherType someOtherType;

  @Before
  public void testSetUp(){
    SomeClassUnderTest someClassToTest = new SomeClassUnderTest();
    someType = EasyMock.createMock(SomeType.class);
    someOtherType = EasyMock.createMock(SomeOtherType.class);
    //How to set dependencies????
  }

  @Test
  public void TestSomeMethodIWouldLikeToTest(){
    //??????
  } 

}

Будет здорово получить толчок в правильном направлении.

Спасибо

4b9b3361

Ответ 1

Вы можете отражать зависимости непосредственно в поле, используя ReflectionTestUtils, например

ReflectionTestUtils.setField( testInstance, "fieldName", fieldValue );

Некоторые утверждают, что предпочтительнее добавлять в класс методу set-view setter, используемому исключительно в тестах. В качестве альтернативы, используйте конструкторы с автосозданием, а не поля с автосогласованием, и вставляйте в них тестовые зависимости.

Ответ 2

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

Было бы лучше добавить публичные сеттеры для этих полей и разместить вместо них аннотации @Autowired. Это не только позволяет избежать отражения, но также разъясняет внешний интерфейс класса и гарантирует, что ваш unit test использует только этот интерфейс. Я вижу, что SomeClassToTest уже реализует интерфейс SomeOtherClass, и я предполагаю, что клиенты SomeClassToTest используют этот интерфейс, поэтому существует небольшая опасность сделать публикаторы на SomeClassToTest общедоступными.

Еще лучше, используйте инъекцию конструктора и сделайте поля окончательными. Вы все еще можете использовать @Autowired в аргументах конструктора.

Ответ 3

Я не рекомендую ответ, который был принят, т.е. используя отражение самостоятельно (без насмешливой структуры).

Начиная с версии 3.2 EasyMock вы можете использовать аннотации, чтобы определять макеты и вводить их в тестируемый класс. Полное описание, как это сделать, можно найти в официальной документации EasyMock: http://easymock.org/user-guide.html#mocking-annotations

Вот пример из вышеупомянутого сайта:

import static org.easymock.EasyMock.*;
import org.easymock.EasyMockRunner;
import org.easymock.TestSubject;
import org.easymock.Mock;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(EasyMockRunner.class)
public class ExampleTest {

  @TestSubject
  private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2

  @Mock
  private Collaborator mock; // 1

  @Test
  public void testRemoveNonExistingDocument() {
    replay(mock);
    classUnderTest.removeDocument("Does not exist");
  }
}