Как инициализировать независимые фиктивные экземпляры в JMockit

Когда я использовал 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: могу ли я получить разные фиктивные экземпляры в тесте на основе состояния?


person NSF    schedule 16.10.2013    source источник


Ответы (1)


В JMockit @Injectable используется для создания отдельных фиктивных экземпляров. Затем можно записать конкретное поведение для каждого имитируемого экземпляра.

В обоих вопросах вы принимаете то, что может (или не может) быть подходом Mockito к тестовому примеру. Другой пример может помочь в понимании проблемы, которую вы пытаетесь решить.

Я не уверен, сможете ли вы сделать то, что пытаетесь сделать с JMockit. Вот менее динамичный метод выполнения того, чего вы пытаетесь достичь. Там, где мне понадобились инъекционные макеты в коллекции в моих собственных тестовых примерах, я использовал этот подход. Я обнаружил, что достаточно проверить поведение; Я понимаю, что это может не иметь дело с более сложным тестовым случаем.

@Injectable App app1;
@Injectable App app2;

@Test
public void testApps() throws Exception {

    final App [] apps = new App[2];
    final String [] names = {"a", "b"};

    apps[0] = app1;
    apps[1] = app2;

    new NonStrictExpectations() {
        {
            app1.getName();
            result = "a";

            app2.getName();
            result = "b";
        }
    };

    for (int i = 0; i < apps.length; i++){
        System.out.println(apps[i].getName());
    }
}

Я понимаю, что могу констатировать очевидное, но в приведенном выше тесте mockito ваш тест просто проверяет конфигурацию вашего тестового примера, а не фактический тестовый код.

person Donal    schedule 17.10.2013
comment
Верно ли в вашем примере, что вам нужно жестко кодировать вводимые аннотации (т.е. вы не можете создавать экземпляры в соответствии с количеством, которое необходимо определить во время выполнения)? - person NSF; 17.10.2013
comment
Да, в моем примере мне пришлось явно объявить все экземпляры, которые я хотел высмеять, чтобы я мог записывать ожидания для них по отдельности. Я пытался, но не смог найти способ создания динамических инъекционных экземпляров, которые затем также могли бы динамически фиксировать ожидания. - person Donal; 18.10.2013