JMockIt Mocked Method не является насмешливым

[10/7/06 4:00 Отредактированный пример кода] Я пытаюсь протестировать некоторый код (используя JMockIt с TestNG), не касаясь базы данных, но похоже, что фактически вызывается фиктивный метод. Вот упрощенная настройка:

class DBRow {
    public DBRow() { }
    public DBRow(Object obj) {
        initialize(obj);
    }
    public void insert() {
        actuallyAddRowToDatabase();
    }
}

class MyObject extends DBRow {
    MyObject(Object obj) {
        super(obj);
    }
    public void insert(Object obj) {
        doSomething(obj);
        insert();
    }
}

class Factory {
    static MyObject createObject(Object obj1, Object obj2) {
        MyObject newObj = new MyObject(obj1);
        newObj.insert(obj2);
        return newObj;
    }
}

Я хотел имитировать операцию вставки, чтобы предотвратить вставку в фактическую базу данных, поэтому я попробовал что-то вроде этого:

@Test
public void testCreation() {
    new Expectations(MyObject.class) {
        MyObject mock = new MyObject(null) {
            @Mock
            public void insert(Object obj) { }
        };
    {
        new MyObject(anyString);   result = mock;
    }};

    MyObject test = Factory.createObject("something", "something else");
}

Но похоже, что настоящий insert(Object) все еще вызывается. Я указываю, что класс является издевательским, так что надо издеваться над всеми экземплярами, верно? И я указываю, что метод вставки должен быть имитирующим, так почему же будет вызван настоящий метод?

С вышесказанным также есть вторая проблема. Когда я определяю фиктивный класс внутри блока Expectations (как указано выше), кажется, что вместо Row(Object) вызывается только конструктор Row(), и, следовательно, объект не инициализирован правильно. Я исправил это, переместив его в @BeforeTest метод и создав там экземпляр класса. Вот как это выглядит:

private MyObject mock;

@BeforeTest
public void beforeTest() {
    new MockUp<MyObject>() {
        @Mock
        public void insert(Object obj) { }
    };
    mock = new MyObject("something");
}

@Test
public void testCreation() {
    new Expectations(MyObject.class) {{
        new MyObject(anyString);   result = mock;
    }};

    MyObject test = Factory.createObject("something", "something else");
}

Таким образом, кажется, что вызывается правильный конструктор, но по-прежнему кажется, что вызывается и insert(). Есть идеи?


person Didjit    schedule 07.10.2016    source источник


Ответы (2)


Вы не используете фиктивный объект для вызова своей функции, т.е. private MyObject mock;, а реальный объект test,

MyObject test = new MyObject("something", "something else");

Звоните testStuff() на mock вместо test.

Все экземпляры не будут автоматически имитироваться, вам придется работать с имитируемыми экземплярами.

person Sabir Khan    schedule 07.10.2016
comment
‹Code› testStuff () ‹/code› не является проблемой. Фактически, я уберу его из своего примера. Проблема заключается в вставке ‹code› () ‹/code› во время строительства. Я собираюсь отредактировать свой пример, чтобы, надеюсь, прояснить его. Однако вы говорите, что все экземпляры не будут автоматически имитироваться, но в документации говорится: «Если объект класса задан [в конструкторе Expectations] ... все экземпляры указанного класса будут рассматриваться как имитирующие экземпляры. Вы можете уточнить свое утверждение? - person Didjit; 07.10.2016
comment
Укажите мне документацию, которую вы цитируете. Поймите, что Expectations фаза записи для вызовов на имитируемых экземплярах. Фаза создания не имитируемого объекта. Мокированные объекты, созданные с помощью new MockUp или Mock и Ìnjectable` - person Sabir Khan; 08.10.2016
comment
Кроме того, очень сложно читать ваш код. У вас MyObjectdefinition есть только один конструктор, MyObject(Object obj), но в вашем тестовом коде он есть, new MyObject("something", "something else");, поэтому я не уверен, на что я смотрю. Если вызываются ваши настоящие методы, это тот случай, когда вы вызываете метод для реального объекта, а не для поддельного. - person Sabir Khan; 08.10.2016
comment
Сабир, спасибо, что нашли время ответить. Прошу прощения за код. Когда я редактировал его, я не обновлял эти конструкторы. Я считаю, что сейчас это непротиворечиво. Что касается цитаты, я нашел ее здесь: ссылка прямо под примером кода. - person Didjit; 09.10.2016

Наконец-то я смог написать свои тесты так, чтобы вызывался правильный конструктор и никаких фактических операций с базой данных не происходило. Я думаю, что часть проблемы, с которой я столкнулся, заключалась в том, что один из методов в блоке Expectations получал другой объект, чем я ожидал для параметра, который меня не интересовал. И я думаю, что другая часть моей проблемы смешивалась роли класса MockUp и записей Expectations.

Тестируемый код не изменился. Вот мой упрощенный пример для удобства:

class DBRow {
    public DBRow() { }
    public DBRow(Object obj) {
        initialize(obj);
    }
    public void insert() {
        actuallyAddRowToDatabase();
    }
}

class MyObject extends DBRow {
    MyObject(Object obj) {
        super(obj);
    }
    public void insert(Object obj) {
        doSomething(obj);
        insert();
    }
}

class Factory {
    static MyObject createObject(Object obj1, Object obj2) {
        MyObject newObj = new MyObject(obj1);
        newObj.insert(obj2);
        return newObj;
    }
}

Вот, по сути, то, что я в конечном итоге получил для тестового кода:

Object something;
Object somethingElse;

@BeforeTest
public void beforeTest() {
    new MockUp<MyObject>() {
        @Mock
        public void insert() { }  // override the "actual" DB insert
    };                            // of Row.insert()
}

@Test
public void testCreation() {
    MyObject mock = new MyObject(something);  // object correctly init'd
                                              // by Row.initialize(Object)
    new Expectations(MyObject.class) {{
        new MyObject(something);     result = mock;
        mock.insert(somethingElse);
    }};

    MyObject test = Factory.createObject(something, somethingElse);
}

Ключевые моменты заключались в том, что: A) я создал класс MockUp для переопределения операций с БД, и B) создал локальный экземпляр этого частично имитируемого экземпляра для записи моих ожиданий.

person Didjit    schedule 10.10.2016