LINUX.ORG.RU

Как работать с mockito?

 , mockito


0

1

Допустим, есть класс:

public class Foo {
   private Bar bar;

   public Foo() {
      bar = new Bar();
   }
   
   public String getBarString() {
      return bar.getString();
   }
}
Как я понял из документации, с помощью mockito можно сделать заглушку для bar:
Bar bar = mock(Bar.class);
when(bar.getString()).thenReturn("some string");

А как теперь эту заглушку интегрировать в класс Foo? Например, класс Bar еще не готов, в телах методов одни //TODO, а Foo нужно уже протестировать.

★★★★★

Последнее исправление: f1xmAn (всего исправлений: 2)

Bar у тебя hardcoded, это плохо с точки зрения дизайна, а его нужно инжектить через конструктор или сеттер, man IoC. Тогда просто заснунь заглушку вместно настоящего Bar

vertexua ★★★★★
()

убрать из класса Foo функциональность по создания Bar и инжектить его при помощи DI. Собственно в Mockito есть свой собственный DI, если не используются какие-нибудь спринги http://docs.mockito.googlecode.com/hg/org/mockito/InjectMocks.html

maloi ★★★★★
()
Ответ на: комментарий от vertexua

А если у меня класс Foo создается на таком уровне, в котором о Bar ничего знать не должны? Как же я его тогда «заинжектю»? Пропустил лекцию, защищая курсовой, теперь аукнулось. ☹

Я наверное тебя неправильно понял, можно пример?

f1xmAn ★★★★★
() автор топика
Ответ на: комментарий от vertexua

ну понятно, что знать про существование такого паттерна полезно, но в данном случае нужно знать про существование DI.

maloi ★★★★★
()
Ответ на: комментарий от f1xmAn

А если у меня класс Foo создается на таком уровне, в котором о Bar ничего знать не должны?

В том то и суть, что Bar или неотъемлемая часть или заменяемая часть. В первом случае тестируется сам Foo, во втором - его нужно инжектить. Причем инжектить может фабрика или билдер например из того же модуля что и Foo. И тогда этот модуль можно тестировать по частям, Bar делать недоступным вне модуля, а Foo создавать фабрикой. Это так, например

vertexua ★★★★★
()

Например так

class Foo {

    private Bar bar;
	
	public Foo() {
	}
	
	public void setBar(Bar bar) {
	    this.bar = bar;
	}
	
	public Bar getBar() {
	    return this.bar;
	}
...
	
}

Bar bar = mock(Bar.class);
when(bar.getString()).thenReturn("some string");

после этого уже можешь делать

    Foo foo = new Foo();
    foo.setBar(bar);
    assertEquals("oh god why", "some string", foo.getBarString());
lester_dev ★★★★★
()

Добавьте второй конструктор:

public class Foo {
   private final Bar bar;

   public Foo() {
      bar = new Bar();
   }
   
   public Foo(Bar bar) {
      this.bar = bar;
   }
   ...
}

и в тестах создавайте объекты через этот конструктор, указывая мокированный bar.

А ещё лучше: уберите конструктор без параметров и пересмотрите логику построения объектов класса Foo

Slavaz ★★★★★
()
Ответ на: комментарий от vertexua

vertexua, maloi, спасибо.
lester_dev, Slavaz, так и собирался изначально сделать, но это показалось некрасивым решением. Спасибо и вам. ☺

f1xmAn ★★★★★
() автор топика
Ответ на: комментарий от lester_dev

А если Bar не является частью абстракции Foo (т.е. Bar всего лишь деталь реализации Foo), то получается ломаем абстракцию исключительно ради тестов?

anonymous
()
Ответ на: комментарий от anonymous

И еще такой вопрос: есть класс A

public class A {
    private static MyLogger logger = MyLogger.create(A.class);

    public int f() {
        logger.debug("f()");

        // implementation...
    }
}

Как протестировать на Mockito метод f, если реализация MyLogger.create, например, читает конфигурационные файлы?

PS: хочется чтобы логгер был статическим

anonymous
()
Ответ на: комментарий от anonymous

Mokito не тестирует, а создает mock-объекты. какой класс ты тут хочешь за-mock-ить? Какая проблема может быть в чтении конфигурационных файлов? пусть читает себе на здоровье.

maloi ★★★★★
()
Ответ на: комментарий от maloi

какой класс ты тут хочешь за-mock-ить?

MyLogger

Какая проблема может быть в чтении конфигурационных файлов? пусть читает себе на здоровье.

Например, откуда брать конфигурационные файлы на машине разработчика? Да и чтение конфигурационных файлов было приведено как пример - можете заменить, опять же например, на чтение конфигурации из БД. А все это я к тому что unit-тесты рекомендуется писать с минимальным кол-вом внешних зависимостей.

anonymous
()
Ответ на: комментарий от anonymous

MyLogger

зачем?

Например, откуда брать конфигурационные файлы на машине разработчика?

из системы контроля версий, для юнит-тестов обычно простейшую конфигурацию логгера делают, которая все в stdout пишет.

Да и чтение конфигурационных файлов было приведено как пример - можете заменить, опять же например, на чтение конфигурации из БД.

и подключение к БД хочется делать при помощи статического поля? ну тогда конечно будут проблемы, как ни старайтесь.

А все это я к тому что unit-тесты рекомендуется писать с минимальным кол-вом внешних зависимостей.

юнит тесты вообще не должны от внешних систем зависеть, как раз для решения этой задачи и служит Mockito - эмулировать поведение внешней системы.

maloi ★★★★★
()
Ответ на: комментарий от maloi

зачем?

Вашими же словами: «эмулировать поведение внешней системы»

и подключение к БД хочется делать при помощи статического поля?

Вы вероятно не понимаете смысл слова «например»?

юнит тесты вообще не должны от внешних систем зависеть, как раз для решения этой задачи и служит Mockito - эмулировать поведение внешней системы.

Это и так ясно. Но судя по вашим ответам вы в теме не разбираетесь.

anonymous
()
Ответ на: комментарий от anonymous

Вашими же словами: «эмулировать поведение внешней системы»

логгер - внешняя система? может вам все-таки стоит почитать, как современные логгеры настраиваются?

Вы вероятно не понимаете смысл слова «например»?

я прекрасно понимаю смысл слова «например», если хотите чтобы вашу мысль понимали правильно - давайте реальные примеры, а не выдуманные.

Это и так ясно. Но судя по вашим ответам вы в теме не разбираетесь.

вы правы, я не разбираюсь в теме расставления себе грабель и попыток найти фреймворк, который за меня эти грабли уберет.

maloi ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.