Пытаюсь понять внедрение зависимостей Java на примере

#java #unit-testing #junit #dependency-injection

#java #модульное тестирование #junit #внедрение зависимостей

Вопрос:

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

У меня есть этот класс, который я хочу убедиться, что он протестирован:

 public class ConnectionFactory {

    private String dataSourceName;

    public ConnectionFactory(String dataSourceName) {

        if(dataSourceName == null) {
            throw new NullPointerException("dataSourceName can't be null");
        }

        this.dataSourceName = dataSourceName;
    }

    public Connection getConnection() throws SQLException {

        Connection connection = getDataSource(dataSourceName).getConnection();

        if(connection != null) {
            return connection;
        }       

        ...
    }

    // Get a datasource object
    private DataSource getDataSource(String dataSourceName) {
        ...
        try {
            Context ctx = new InitialContext();
            dataSource = (DataSource) ctx.lookup("java:comp/env/"   dataSourceName);
        } catch (NamingException e) {
            ...
        }

        return dataSource;
    }

}
  

Я хочу иметь возможность просто вызывать этот класс из всех моих приложений с помощью чего-то такого простого, как это:

 public class MyApp {
    public static void main(string[] args) {
        ConnectionFactory connectionFactory = new ConnectionFactory("jdbc/myDataSource");
        Connection connection = connectionFactory.getConnection();
    }
}
  

Я начал писать модульные тесты для этого ConnectionFactory, но быстро понял, что с моим текущим кодом я не могу имитировать объект DataSource, поэтому он пытается фактически подключиться к реальному источнику данных.

 @RunWith(Nested.class)
public class ConnectionFactoryTest {

    public class Constructor {

        @Test
        public void shouldThrowNullPointerIfParamIsNull() {
            assertThatExceptionOfType(NullPointerException.class)
                .isThrownBy(() -> { new ConnectionFactory(null); })
                .withMessage("dataSourceName can't be null");
        }
    }

    public class GetConnection {

        public class WithDataSourceAvailable {

            @Test
            public void shouldErrorIfParamIsNull() {
                ConnectionFactory connectionFactory = new ConnectionFactory("jdbc/myDataSource"); // <-- This is going to fail b/c it's trying to actually fetch a real data source
            }
        }   
    }
}
  

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

Комментарии:

1. «Я не могу издеваться над объектом источника данных» это утверждение неверно. Можно имитировать создание объекта с помощью таких инструментов, как PowerMock.

2. «Я не могу издеваться» означает, что я не знаю, как это издеваться.

Ответ №1:

Взгляните на Mockito, я нахожу его простым в использовании для такого типа макетирования.