Java - 构造函数单元测试

Java - Constructor Unit testing

我有以下 Java 配置 class 我需要使用 JUnit 进行单元测试:

public class Config {

private static final String AMQ_CONNECTION_URL_TEMPLATE = "failover:(%s)";
private final String awsAmqUrl;

public Config(String url, Optional<String> amqConnectionOptions, PropertiesManager propertiesManager) {
    String urlParameter = propertiesManager.getStringParameter(url);
    this.awsAmqUrl = constructAmqConnectionString(urlParameter, amqConnectionOptions);
}

private String constructAmqConnectionString(String urlParameter, Optional<String> connectionOptions) {
    if (connectionOptions.isPresent()) {
        urlParameter = Stream.of(urlParameter.split(","))
                .map(url -> url + "?" + connectionOptions.get())
                .collect(Collectors.joining(","));
    }
    return String.format(AMQ_CONNECTION_URL_TEMPLATE, urlParameter);
}

public ConnectionFactory getConnectionFactory() {
    ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(awsAmqUrl);
    return connectionFactory;
}
}

我正在努力寻找 constructAmqConnectionString 方法单元测试的最佳解决方案,因为它被标记为私有。 我试图涵盖 3 种情况:

目前的解决方案是在Config class中为awsAmqUrl字段添加一个getter,这样构造函数的调用逻辑就可以是verified/tested:

public String getAwsAmqUrl() {
    return this.awsAmqUrl;
}

测试本身具有以下逻辑:

@Test
public void verifyConstructorWithoutMqOptionsMultiBroker() {
    when(propertiesManager.getStringParameter(any())).thenReturn("url1,url2");
    Optional<String> amqConnectionOptions = Optional.empty();
    config = new Config("url1,url2", amqConnectionOptions, propertiesManager);
    assertEquals(String.format("failover:(url1,url2)"),config.getAwsAmqUrl());
}

@Test
public void verifyConstructorWithMqOptionsMultiBroker() {
    when(propertiesManager.getStringParameter(any())).thenReturn("url1,url2");
    Optional<String> amqConnectionOptions = Optional.of("optionTest=1");
    config = new Config("url1,url2", amqConnectionOptions, propertiesManager);        
    assertEquals(String.format("failover:(url1?%1$s,url2?%1$s)",amqConnectionOptions.get()),config.getAwsAmqUrl());
}

@Test
public void verifyConstructorWithMqOptionsSingleBroker() {
    when(propertiesManager.getStringParameter(any())).thenReturn("url1");
    Optional<String> amqConnectionOptions = Optional.of("optionTest=1");
    config = new Config("url1", amqConnectionOptions, propertiesManager);                
    assertEquals(String.format("failover:(url1?%1$s)",amqConnectionOptions.get()),config.getAwsAmqUrl());
}

仅出于单元测试目的添加 getter 感觉不对,因为它破坏了封装。 在这种情况下是否有更好的方法来进行测试?

您的 class 使用 awsAmqUrl 的唯一地方是在 getConnectionFactory 方法中。所以看起来这是您必须使用的方法,以确保 awsAmqUrl 的值是正确的。因此,不要为 awsAmqUrl 使用 getter,而是使用类似

的东西
String storedUrl = objectUnderTest.getConnectionFactory().getBrokerUrl();

然后你可以对 URL 做出断言。

当然,它使您的测试依赖于 ActiveMQConnectionFactory 的行为 - 但没关系,因为您的 class 无论如何都与特定的 class 紧密耦合。