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




scanner junit (6)

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

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

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

@Resource
private MyLauncher myLauncher ;

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

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

@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)

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


Иногда вы можете реорганизовать свой @Component для использования инъекции на основе конструктора или сеттера, чтобы настроить @Autowired (вы можете и все еще полагаться на @Autowired ). Теперь вы можете полностью создать свой тест без издевательских фреймворков, заменив тестовые заглушки (например, MailServiceStub Мартина Фоулера):

@Component
public class MyLauncher {

    private MyService myService;

    @Autowired
    MyLauncher(MyService myService) {
        this.myService = myService;
    }

    // other methods
}

public class MyServiceStub implements MyService {
    // ...
}

public class MyLauncherTest
    private MyLauncher myLauncher;
    private MyServiceStub myServiceStub;

    @Before
    public void setUp() {
        myServiceStub = new MyServiceStub();
        myLauncher = new MyLauncher(myServiceStub);
    }

    @Test
    public void someTest() {

    }
}

Этот метод особенно полезен, если тест и тестируемый класс находятся в одном пакете, потому что тогда вы можете использовать модификатор доступа к package-private доступу по умолчанию, чтобы другие классы не обращались к нему. Обратите внимание, что вы все равно можете иметь свой производственный код в src/main/java но ваши тесты в каталогах src/main/test .

Если вам нравится Mockito, тогда вы по достоинству оцените MockitoJUnitRunner . Это позволяет вам делать «магические» вещи, такие как @Manuel показал вам:

@RunWith(MockitoJUnitRunner.class)
public class MyLauncherTest
    @InjectMocks
    private MyLauncher myLauncher; // no need to call the constructor

    @Mock
    private MyService myService;

    @Test
    public void someTest() {

    }
}

Кроме того, вы можете использовать бегун JUnit по умолчанию и вызывать MockitoAnnotations.initMocks() в setUp() чтобы Mockito инициализировал аннотированные значения. Вы можете найти дополнительную информацию в javadoc @InitMocks и в сообщении в блоге, которое я написал.


Принятый ответ (используйте 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);
        }
    }

Я новый пользователь для Spring. Я нашел другое решение для этого. Использование рефлексии и создание общедоступных полей и назначение макетных объектов.

Это мой авторизационный контроллер, и у него есть некоторые личные свойства Autwired.

@RestController
public class AuthController {

    @Autowired
    private UsersDAOInterface usersDao;

    @Autowired
    private TokensDAOInterface tokensDao;

    @RequestMapping(path = "/auth/getToken", method = RequestMethod.POST)
    public @ResponseBody Object getToken(@RequestParam String username,
            @RequestParam String password) {
        User user = usersDao.getLoginUser(username, password);

        if (user == null)
            return new ErrorResult("Kullanıcıadı veya şifre hatalı");

        Token token = new Token();
        token.setTokenId("aergaerg");
        token.setUserId(1);
        token.setInsertDatetime(new Date());
        return token;
    }
}

И это мой тест Junit для AuthController. Я делаю публичные необходимые частные свойства и присваиваю им макетные объекты и рок :)

public class AuthControllerTest {

    @Test
    public void getToken() {
        try {
            UsersDAO mockUsersDao = mock(UsersDAO.class);
            TokensDAO mockTokensDao = mock(TokensDAO.class);

            User dummyUser = new User();
            dummyUser.setId(10);
            dummyUser.setUsername("nixarsoft");
            dummyUser.setTopId(0);

            when(mockUsersDao.getLoginUser(Matchers.anyString(), Matchers.anyString())) //
                    .thenReturn(dummyUser);

            AuthController ctrl = new AuthController();

            Field usersDaoField = ctrl.getClass().getDeclaredField("usersDao");
            usersDaoField.setAccessible(true);
            usersDaoField.set(ctrl, mockUsersDao);

            Field tokensDaoField = ctrl.getClass().getDeclaredField("tokensDao");
            tokensDaoField.setAccessible(true);
            tokensDaoField.set(ctrl, mockTokensDao);

            Token t = (Token) ctrl.getToken("test", "aergaeg");

            Assert.assertNotNull(t);

        } catch (Exception ex) {
            System.out.println(ex);
        }
    }

}

Я не знаю преимуществ и недостатков, но это работает. У этой техники есть немного больше кода, но эти коды могут быть разделены различными методами и т. Д. Есть более хорошие ответы на этот вопрос, но я хочу указать на другое решение. Извините за мой плохой английский. Имейте хороший java для всех :)


Вы можете абсолютно вводить макеты в MyLauncher в свой тест. Я уверен, что если вы покажете, какую издевательскую структуру вы используете, кто-то быстро даст ответ. С mockito я бы рассмотрел использование @RunWith (MockitoJUnitRunner.class) и использование аннотаций для myLauncher. Он будет выглядеть примерно так, как показано ниже.

@RunWith(MockitoJUnitRunner.class)
public class MyLauncherTest
    @InjectMocks
    private MyLauncher myLauncher = new MyLauncher();

    @Mock
    private MyService myService;

    @Test
    public void someTest() {

    }
}

Вот пример того, как мои тесты работают с Spring 3.1, JUnit 4.7 и Mockito 1.9:

FooService.java

public class FooService {
    @Autowired private FooDAO fooDAO;
    public Foo find(Long id) {
        return fooDAO.findById(id);
    }
}

FooDAO.java

public class FooDAO {
    public Foo findById(Long id) {
        /* implementation */
    }
}

FooServiceTest.java

@RunWith(MockitoJUnitRunner.class)
public class FooServiceTest {
    @Mock private FooDAO mockFooDAO;
    @InjectMocks private FooService fooService = new FooService();

    @Test public final void findAll() {
        Foo foo = new Foo(1L);
        when(mockFooDAO.findById(foo.getId()).thenReturn(foo);

        Foo found = fooService.findById(foo.getId());
        assertEquals(foo, found);
    }
}




java spring unit-testing junit autowired