Когда я использовал Mockito, я мог легко создать издевательский экземпляр. Но в JMockit все не так просто. Чтобы проиллюстрировать мою идею, давайте использовать этот пример:
public class App {
private String name;
public App(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Это просто очень простая неизменяемая оболочка. Чтобы протестировать его с помощью Mockito, я могу написать такой код:
List<App> mockApps = new ArrayList<App>();
String[] fakeNames = new String[] {"a", "b", "c"};
for (String name : fakeNames) {
// create a mocked instance
// I don't care if the class has a default ctor or not
App mockApp = mock(App);
when(mockApp.getName()).thenReturn(name);
// add to the container
mockApps.add(mockApp);
}
// assertions
for (int i = 0; i < fakeNames.length; i++) {
assertThat(mockApps.get(i).getName(), is(fakeNames[i]));
}
Однако в JMockit все меняется: (я могу что-то упустить)
Чтобы получить тот же результат, мне нужно сделать:
@Mocked App app; // let JMockit kick in for this class
List<App> mockApps = new ArrayList<App>();
String[] fakeNames = new String[] {"a", "b", "c"};
for (final String name : fakeNames) {
// create a mocked instance
// DIFFERENCE: I have to use the ctor provided by App class
// I actually can just pass "name" to the ctor here in this example
// but let's assume getName() in reality has much more complex logic
App mockApp = new App(null);
new NonStrictExpectations(mockApp) {
mockApp.getName(); result = name;
}
mockApps.add(mockApp);
}
// assertions
for (int i = 0; i < fakeNames.length; i++) {
assertThat(mockApps.get(i).getName(), is(fakeNames[i]));
}
Я не уверен, что это правильный подход, но он работает. И я думаю, что это называется поведенческим тестом.
Вопрос 1: Могу ли я обойти ctor? (Кажется, я могу просто пройти все нули, но я даже не хочу этого делать .)
Есть еще один вопрос, касающийся теста на основе состояния в JMockit:
Если я сделаю это для достижения экземпляров:
List<App> mockApps = new ArrayList<App>();
String[] fakeNames = new String[] {"a", "b", "c"};
for (final String name : fakeNames) {
new MockUp<App> {
@Mock
public String getName() {
return name;
}
}
App mockApp = new App(null);
mockApps.add(mockApp);
}
Все становится еще хуже, поскольку все mockApps возвращают «c» в качестве своего имени. Кажется, что во время выполнения всегда может быть только один издевательский класс, и все, что будет определено позже, заменит прежние, что, я думаю, не имеет смысла.
Итак, Вопрос 2: могу ли я получить разные фиктивные экземпляры в тесте на основе состояния?