java test scanner - Инъекция @Полученное личное поле во время тестирования





3 Answers

Принятый ответ (используйте MockitoJUnitRunner и @InjectMocks ) отлично. Но если вы хотите что-то немного более легкое (без специального бегуна JUnit) и менее «волшебное» (более прозрачное), особенно для случайного использования, вы можете просто установить частные поля непосредственно с помощью интроспекции.

Если вы используете Spring, у вас уже есть класс утилиты для этого: org.springframework.test.util.ReflectionTestUtils

Использование довольно просто:

ReflectionTestUtils.setField(myLauncher, "myService", myService);

Первый аргумент - ваш целевой компонент, второй - имя (обычно частного) поля, а последним - значение для ввода.

Если вы не используете Spring, довольно просто реализовать такой метод утилиты. Вот код, который я использовал до того, как нашел этот класс Spring:

public static void setPrivateField(Object target, String fieldName, Object value){
        try{
            Field privateField = target.getClass().getDeclaredField(fieldName);
            privateField.setAccessible(true);
            privateField.set(target, value);
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }
junit console input

У меня есть компонентная установка, которая по сути является программой запуска приложения. Он настроен так:

@Component
public class MyLauncher {
    @Autowired
    MyService myService;

    //other methods
}

MyService аннотируется аннотацией @Service Spring и автоматически отключается в моем классе запуска без каких-либо проблем.

Я хотел бы написать некоторые тестовые примеры jUnit для MyLauncher, чтобы сделать это, я начал класс следующим образом:

public class MyLauncherTest
    private MyLauncher myLauncher = new MyLauncher();

    @Test
    public void someTest() {

    }
}

Могу ли я создать объект Mock для MyService и ввести его в myLauncher в своем тестовом классе? У меня в настоящее время нет геттера или сеттера в myLauncher, так как Spring обрабатывает автоустановку. Если возможно, я бы не хотел добавлять геттеры и сеттеры. Могу ли я сообщить тестовому примеру, чтобы ввести объект-макет в переменную с использованием метода @Before init?

Если я собираюсь сделать это совершенно неправильно, не стесняйтесь это говорить. Я все еще новичок в этом. Моя главная цель - просто иметь некоторый Java-код или аннотацию, которая помещает макет в эту переменную @Autowired без необходимости писать метод setter или использовать файл applicationContext-test.xml. Я бы предпочел сохранить все для тестовых случаев в .java-файле вместо того, чтобы поддерживать отдельный applicationContent только для моих тестов.

Я надеюсь использовать Mockito для фальшивых объектов. Раньше я делал это, используя org.mockito.Mockito и создавая свои объекты с помощью Mockito.mock(MyClass.class)

Большое спасибо.




Посмотрите на эту link

Затем напишите свой тестовый пример как

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext.xml"})
public class MyLauncherTest{

@Resource
private MyLauncher myLauncher ;

   @Test
   public void someTest() {
       //test code
   }
}



Я считаю, что для того, чтобы иметь возможность автоматической проводки в классе MyLauncher (для myService), вам нужно будет позволить Spring инициализировать его вместо вызова конструктора путем автоматической проводки myLauncher. Как только это будет автоматически подключено (и myService также будет автоматически подключен), Spring (1.4.0 и выше) предоставляет аннотацию @MockBean, которую вы можете добавить в свой тест. Это заменит совпадающие отдельные компоненты в контексте с макетом этого типа. Затем вы можете определить, какое издевательство вы хотите, в методе @Before.

public class MyLauncherTest
    @MockBean
    private MyService myService;

    @Autowired
    private MyLauncher myLauncher;

    @Before
    private void setupMockBean() {
        doNothing().when(myService).someVoidMethod();
        doReturn("Some Value").when(myService).someStringMethod();
    }

    @Test
    public void someTest() {
        myLauncher.doSomething();
    }
}

Затем ваш класс MyLauncher останется немодифицированным, а ваш компонент MyService будет макетом, методы которого возвращают значения, как вы определили:

@Component
public class MyLauncher {
    @Autowired
    MyService myService;

    public void doSomething() {
        myService.someVoidMethod();
        myService.someMethodThatCallsSomeStringMethod();
    }

    //other methods
}

Пара преимуществ этого над другими упомянутыми способами заключается в том, что:

  1. Вам не нужно вручную вводить myService.
  2. Вам не нужно использовать бегун или правила Mockito.





Related