2015-06-29 1 views
0

У меня есть класс, который является чем-то вроде этого (очень упрощенное, но это общая идея, я действительно не используется необработанный типа сокета.):Dependency Injection для модульного тестирования в сравнении класса управления своим собственных переменных

class ConnectionBroker { 

    private Socket socket; 

    public ConnectionBroker(ConnectionDetails details) { 
     socket = new Socket(details) 
     //set socket paramaters 
    } 

    public sendOverConnection(String message) { 
     //processing of message and internal queuing based on priority 
     socket.send(message); 
    } 

    public shutdown() { 
     socket.close(); 
    } 
} 

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

public ConnectionBroker(Socket socket) { 
    this.socket = socket; 
} 

Это позволит сделать блок тестирования намного проще, однако у меня есть ряд вопросов с делать это таким образом:

  • розетка должна быть maanged только ConnectionBroker класса
  • Тот факт, что ConnectionBroker класс использует сокеты на все должны быть отведенной от класса вызывающего
  • Если сокет должен быть принят в то вызывающий код мог бы модифицировать атрибуты в гнезде, которые класс ConnectionBroker не знает

Каков правильный способ решения этого вопроса? Я что-то неправильно думаю?

+0

непубличный 'ConnectionBroker (гнездо сокета)'? – ZhongYu

ответ

1

Не уверен, что стандартный номер ConnectionBroker(Socket socket) имеет свои плюсы и минусы, как вы указали.

Очевидно, что проблемный бит вашего кода - это вызов new Socket(details), что затрудняет тестирование.

В почти подобный сценарий я ввел новую зависимость SocketProvider с одним методом getSocket(), который заканчивает создание сокета:

public Socket getSocket() { return new Socket();

Это делает тривиальной для модульных тестов, чтобы обеспечить реализацию или подкласс возвращает mock/stub/spy ... Например

@Mock 
private Socket mockedSocket; 
@Mock 
private SocketProvider mockedProvider; 

// ... 
conncectionBroker.setSocketProvider(mockedProvider); 

// ... 

when(mockedProvider.getSocket()).return(mockedSocket); // or a stub/spy/testSocket... 

Она также позволяет обеспечить различные реализации для различных сред и сценариев тестирования - что ИМО делает его лучше подход к тому, что вы предложили (где логика создания лежит в пределах ответственности отдельного теста).

+0

Спасибо, Jan, какова будет ваша реализация '' SocketProvider''? Это статический класс? – Sam

+0

Ну, это должен код, который затрудняет тестирование 'ConnectionBroker' ... (что является фактическим созданием сокета с' new Socket() ') –

+0

@jangroth в конструкторе, если Socket is beign прошло, тогда он не будет делать на нем ничего нового. поэтому это si так же, как получение сокета, переданного в конструкторе, более раздражающим способом его выполнения. –