Прежде всего: я не вижу никаких проблем с вашей ConnectionFactory, если она не содержит никакого состояния (которое, похоже, не содержит). В этом случае проблемы с тестированием не возникают из-за статического заводского метода.
Код модульного тестирования, который напрямую взаимодействует с элементами среды, такими как файловая система, база данных или сеть, всегда сложен. В этом случае вам потребуется смоделировать создание сокета, и это, вероятно, не стоит затраченных усилий. Даже если бы вы сделали это, тестовый код был бы большим, сложным в обслуживании и хрупким.
Пожалуйста, пересмотрите, почему вы хотите написать модульный тест для этого класса ...
Эта фабрика соединений может быть легче охвачена тестом интеграция . Вы можете настроить локальный сервер сокетов, записать полученный ввод и смоделировать отправленный вывод. Примерно так:
public class TestServer {
private int port;
private String[] responses;
private List<String> inputLines = new ArrayList<String>();
public TestServer(int port, String ... responses) {
this.port = port;
this.responses = responses;
}
public void run() throws IOException {
ServerSocket serverSocket = new ServerSocket(port);
Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
int i = 0;
while ((inputLine = in.readLine()) != null) {
inputLines.add(inputLine);
out.println(responses[i++]);
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
public List<String> getInputLines() {
return inputLines;
}
}
Ваш тестовый код может выглядеть примерно так:
// setup
String sentInput = "hello";
String sentOutput = "hi there!";
int port = 4444;
TestServer server = new TestServer(port, sentOutput);
server.run();
// test
Connection connection = ConnectionFactory.createConnection(ConnectionType.TCP, "localhost", port);
// not sure of your Connection's API
connection.open();
String receivedOutput = connection.send(sentInput);
connection.close();
// verify
List<String> inputLines = server.getInputLines();
assertEquals(sentInput , inputLines.get(0));
assertEquals(sentOutput, receivedOutput);
Надеюсь, это поможет.
РЕДАКТИРОВАТЬ : Хорошо, поэтому я немного неправильно понял ваш вопрос, извините. Вышеупомянутый подход все еще является верным решением, я думаю. Это позволит вам сохранить ваши статические фабричные методы и запустить интеграционный тест. Тем не менее, ваше желание unittest ваш метод обслуживания имеет смысл. Решение, которое вы выбрали (переопределяя connectToHost в вашем сервисе), кажется мне довольно хорошим. Еще один способ сделать это так:
Создать интерфейс для переноса зависимости:
public interface ConnectionProvider {
Connection provideConnection(ConnectionType connectionType);
}
Завершите вызов на заводе и добавьте сеттер:
private ConnectionProvider connectionProvider = new ConnectionProvider() {
public Connection provideConnection(ConnectionType connectionType) {
return ConnectionFactory.createConnection(connectionType, "domain.com", 40203);
}
};
public void setConnectionProvider(ConnectionProvider connectionProvider) {
this.connectionProvider = connectionProvider;
}
Позвоните своему провайдеру соединения вместо прямого вызова фабрики:
public void initConnectionPool(ConnectionType connectionType) {
for (int i = 0; i < MAX_CONNECTIONS; i++) {
connectionList.add(connectionProvider.provideConnection(connectionType));
}
// Some more code here to do further processing
// ......
// ......
}
В вашем юнит-тесте используйте сеттер, чтобы создать макет.