Отредактировано: переписал вопрос короче. Спасибо за указание на это! :)
Мне нужно написать тесты JUnit, где я должен издеваться над парой частных методов и полей без установки/получения. Я попробовал два способа сделать это: с Mockito и PowerMock. Вопрос в том, можно ли их совместить? Первая попытка протестировать метод с закрытым полем:
...
@Mock private XMLConfiguration config;
@InjectMocks AAIGroupController groupi;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
...
given(config.configurationsAt(anyString())).willReturn(ldapGroups);
...
Вторая попытка PowerMock протестировать закрытый метод:
...
AAIGroupController groupC = PowerMockito.spy(new AAIGroupController());
...
when(groupC, method(AAIGroupController.class, "getLdapGroupNodeFromGroupConfigFile", ELUser.class))
.withArguments(any(ELUser.class))
.thenReturn(sn);
assertTrue(iaigroupi.isPosixAccount(new ELUserAAI(null, true, false)));
...
Есть ли способ их объединить, или я должен использовать только PowerMock? У меня возникли проблемы с насмешкой над частным полем с помощью PowerMock.
Другой вопрос: мне нужно написать тесты JUnit для интерфейсов. Разве это ерунда, так как классы, реализующие интерфейсы, уже протестированы. И если нет, то что было бы хорошей практикой для этого?
Заранее спасибо!
Старый вопрос, можно вообще пропустить. Я просто оставил это здесь для понимания уже данных ответов.
Мне нужно написать тесты JUnit для интерфейсов, где реализация уже сделана. Но я немного запутался, как правильно писать для них тесты. Я начал с реализации, но сейчас застрял. Во-первых, я не уверен, правильно ли я тестирую интерфейсы, а затем возникает проблема с насмешкой над частным полем. До сих пор я написал два разных тестовых класса, чтобы попробовать что-то. Оба тестовых класса «работают» прямо сейчас, но я хотел бы объединить их в класс InterfaceAAIGroupControllerTest, но не знаю, как использовать Mockito в PowerMock. Для интерфейса я использую
groupi = PowerMockito.spy(new AAIGroupController());
и для другого теста я использую
@Mock private XMLConfiguration config;
@InjectMocks AAIGroupController groupi;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
Для кода:
Интерфейс:
public interface IAAIGroupController {
/**
* Appends a new group entry
*/
public void appendGroup();
/**
* checks if a given account is a possix account
*
* @param elUser the user object to check
* @return true if is posix, otherwise false
* @throws ConfigurationException
*/
public boolean isPosixAccount(ELUser elUser)
...
Реализация
@Override
public void appendGroup() {
try {
config.addProperty("ldapGroup(-1)",
List<SubnodeConfiguration> ldapGroups = config.configurationsAt("ldapGroup");
SubnodeConfiguration sn = ldapGroups.get(ldapGroups.size()-1);
try {
sn.addProperty("script(-1)", null);
// TODO Configuration
} catch (Exception e) {
sn.addProperty("script(-1)", "default.sh");
}
config.save();
} catch (ConfigurationException ex) {
LOGGER.log(Level.SEVERE, ex.getMessage());
}
}
@Override
public boolean isPosixAccount(final ELUser elUser) throws ConfigurationException {
SubnodeConfiguration ldapGroup = getLdapGroupNodeFromGroupConfigFile(elUser);
String posix = ldapGroup.getString("[@posix]");
if (posix == null || posix.isEmpty() || posix.equalsIgnoreCase("true")) {
return true;
} else if (posix.equalsIgnoreCase("false")) {
return false;
} else {
throw new ConfigurationException("posix attribute is not set properly!");
}
}
Код тестирования интерфейса, который пока плохо обрабатывает исключения, исправит это, когда заработает. Я использую PowerMock, так как мне нужно вызывать частные методы в реализации. Я не знаю, смогу ли я хорошо тестировать интерфейсы таким образом.
@RunWith(PowerMockRunner.class)
@PrepareForTest(AAIGroupController.class)
public class InterfaceAAIGroupControllerTest {
public IAAIGroupController iaigroupi;
public AAIGroupController groupi;
public XMLConfiguration config;
@Before
public void setUp() {
groupi = PowerMockito.spy(new AAIGroupController());
config = Whitebox.getInternalState(groupi, "config");
iaigroupi = groupi;
}
@Test
public void isPosixAccount_True() {
try {
SubnodeConfiguration sn = mock(SubnodeConfiguration.class);
when(iaigroupi, method(AAIGroupController.class, "getLdapGroupNodeFromGroupConfigFile", ELUser.class))
.withArguments(any(ELUser.class))
.thenReturn(sn);
assertTrue(iaigroupi.isPosixAccount(new ELUserAAI(null, true, false)));
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Тестовый код для реализации, здесь я использую Mockito для имитации частного поля, которое используется в коде, но никогда не устанавливается конструктором или методом.
@RunWith(MockitoJUnitRunner.class)
public class AAIGroupControllerTest {
@Mock private XMLConfiguration config;
@InjectMocks AAIGroupController groupi;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void appendGroupTest() {
List<SubnodeConfiguration> ldapGroups = mock(List.class);
SubnodeConfiguration sn = mock(SubnodeConfiguration.class);
given(config.configurationsAt(anyString())).willReturn(ldapGroups);
given(ldapGroups.size()).willReturn(11);
given(ldapGroups.get(ldapGroups.size()-1)).willReturn(sn);
groupi.appendGroup();
verify(sn).addProperty("script(-1)", null);
}
}
Мои проблемы прямо сейчас: могу ли я протестировать интерфейс, как я? Не кажется хорошим решением. Параметризация кажется ненужной, так как всегда будет только одна реализация, и я понятия не имею, как использовать два бегуна. Другое дело, как я могу использовать тестовый код из последнего примера, где я издеваюсь над частным полем «config», в тестовом классе PowerMock? Я не знаю, как правильно издеваться над частным полем и изменять его поведение, когда из него вызывается метод.
Заранее спасибо за каждый совет!