Spring 3 автоувеличивание и тестирование юнита
Мой код:
@Component
public class A {
@Autowired
private B b;
public void method() {}
}
public interface X {...}
@Component
public class B implements X {
...
}
Я хочу протестировать в классе изоляции A. Должен ли я высмеивать класс B? Если да, то как? Потому что он автообновлен, и нет сеттера, где я мог бы отправить насмешливый объект.
Ответы
Ответ 1
Я хочу протестировать в классе изоляции A.
Вы должны абсолютно издеваться над B, а не создавать экземпляр и вводить экземпляр B. Цель состоит в том, чтобы проверить A, работает ли B, поэтому вы не должны допускать, чтобы потенциально поврежденный B мешал тестированию A.
Тем не менее, я настоятельно рекомендую Mockito. Как издевательские рамки идут, он чрезвычайно прост в использовании. Вы должны написать что-то вроде следующего:
@Test
public void testA() {
A a = new A();
B b = Mockito.mock(B.class); // create a mock of B
Mockito.when(b.getMeaningOfLife()).thenReturn(42); // define mocked behavior of b
ReflectionTestUtils.setField(a, "b", b); // inject b into the B attribute of A
a.method();
// call whatever asserts you need here
}
Ответ 2
Вот пример того, как мои тесты работают с 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);
}
}
Ответ 3
Вы можете ввести поле через отражение, используя Spring ReflectionTestUtils.setField
(или расширение junit PrivateAccessor
), или вы можете создать контекст прикладного приложения и загрузить его. Хотя для простого теста (неинтеграции) я предпочитаю использовать отражение для простоты.
Ответ 4
Это обсуждение форума имеет смысл для меня. Вы можете объявить своего частного члена b как тип интерфейсаB, который реализуется классом B (т.е. Сервисно-ориентированным), а затем объявить класс MockB, который также реализует тот же интерфейс. В контексте приложения тестовой среды вы объявляете класс MockB и контекст вашего производственного приложения, который вы объявляете обычным классом B, и в любом случае код для класса A не нужно изменять, поскольку он будет автоматически подключен.