gpt4 book ai didi

java - 如何构建应用程序以帮助测试 sql

转载 作者:行者123 更新时间:2023-11-28 21:30:18 26 4
gpt4 key购买 nike

我正在编写一个应用程序 - 我认为我的设计不是很好。我使用一个名为 ExposedFunctions 的类,它包含用于请求我的 Web 服务的 @WebMethod 逻辑。这些方法通常需要从内部缓存读取或转到数据库。因此我有一个 DBFactory 类,它有单独的数据库操作方法。下面是这种结构的示例

ExposedFunctions

@WebService
public class ExposedFunctions {

private static Logger logger = Logger.getLogger(ExposedFunctions.class);
private DBFactory factory = new DBFactory();


@WebMethod
public String register(String username, String password, String email, String firstname, String lastname) {
if(StringUtilities.stringEmptyOrNull(username) ||
StringUtilities.stringEmptyOrNull(password) ||
StringUtilities.stringEmptyOrNull(email) ||
StringUtilities.stringEmptyOrNull(firstname) ||
StringUtilities.stringEmptyOrNull(lastname)){
logger.error("String was null or empty when registering");
}

RegistrationStatus status = factory.register(username, password, email, firstname, lastname);
return status.getValue();
}
}

数据库工厂

public class DBFactory {

private final BasicDataSource source = new BasicDataSource();
private final Logger logger = Logger.getLogger(DBFactory.class);

public DBFactory() {

try {
setupConnections();
} catch (DatabasePropertyException e) {
logger.info("Unable to load the properties file", e);
System.exit(1);
}
}

private void setupConnections() throws DatabasePropertyException{
Properties props = DatabaseUtilities.getDatabaseConnectionProps("/swiped.properties");
if(props != null){
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUsername(props.getProperty("username"));
source.setPassword(props.getProperty("password"));
source.setUrl(props.getProperty("url_local"));
source.setMaxActive(-1);
}else{
throw new DatabasePropertyException("Unable to load the proeprties file in order to connect to the database - exiting application");
}
}

public RegistrationStatus register(String username, String password, String email, String firstname, String lastname) {

String sql = "INSERT INTO Users (username, password, email, firstname, lastname) values (?,?,?,?,?)";
RegistrationStatus status = null;
Connection conn = null;
PreparedStatement st = null;
try {
conn = source.getConnection();
st = conn.prepareStatement(sql);
st.setString(1, username);
st.setString(2, password);
st.setString(3, email);
st.setString(4, firstname);
st.setString(5, lastname);
st.executeUpdate();
status = RegistrationStatus.SUCCESSFUL;
}
catch (MySQLIntegrityConstraintViolationException e) {
logger.warn("Unable to register user " + username + " as they are already registered");
return RegistrationStatus.USER_ALREADY_REGISTERED;
}catch(Exception e){
logger.error("Unable to insert a new user in to the database", e);
status = RegistrationStatus.FAILED;
}finally{
DatabaseUtilities.closeConnection(conn);
DatabaseUtilities.closePreparedStatement(st);
}
return status;
}

此设置使我很难进行测试,因为 1) DBFactory 绑定(bind)到特定的数据库连接 - 这意味着其中的数据很可能会发生变化,并且测试会不规律地通过和失败。还有另一个问题是 DBFactory 可以达到 2000 多行代码,这也不理想。

请有人建议一些改进此设计的方法,以增加/最大化我的测试工作,并帮助确保更好的可维护性和可扩展性。

谢谢

最佳答案

好吧,您至少需要测试 3 个级别,并且需要对您的代码进行一些小的修改以使其更容易:

1。对调用 DbFactory 的代码进行单元测试。

很高兴您已经抽象出实际与数据库交互的代码,因为这样更容易测试。如果您修改 ExposedFunctions 以便您可以在测试期间传入或注入(inject)不同的 DbFactory 实例,那么您的测试可以使用模拟 DbFactory。模拟工厂可以确保您的代码传递正确的参数,并且您可以在不实际接触真实数据库的情况下测试各种错误情况。您可能需要做的就是添加一个构造函数或设置方法来修改您的 dbFactory 字段:

public class ExposedFunctions {

...
private DBFactory factory;

public ExposedFunctions(){
this(new DBFactory());
}

public ExposedFunctions(DbFactory factory){
Objects.requireNonNull(factory);
this.factory = factory;
}
...
}

2。修改您的 DbFactory 类以模拟 Connection

如果您在 DbFactory 类中做类似的事情以便您可以模拟 Connection 那么您针对 DbFactory 的测试也没有打一个真正的数据库。通过模拟连接及其返回的语句,您可以验证是否针对给定参数执行了正确的 SQL 代码,并测试各种 SQLException 条件以模拟在现实世界中难以测试的连接或数据问题。

3。针对测试(在内存中?)数据库进行测试

实际连接到真实数据库以确保一切正常作为集成测试的一部分也是一个好主意。不要连接到生产环境!您可以通过使用不同的属性文件或注入(inject)不同的连接对象来交换连接,如#2 中所示。有图书馆,如dbUnit帮助使用测试数据库。还有内存数据库,如 derbyhsqldb它们是轻量级的,可以让您比连接到“常规”数据库更快地运行测试。但是,请注意内存数据库,它与您选择的数据库供应商不完全相同的环境或 SQL 解释器。 SQL 或模式设计中可能存在差异,这可能会让您认为您的代码在测试通过后可以正常工作,但随后在使用相同代码的生产中会出现错误。

希望对你有帮助

关于java - 如何构建应用程序以帮助测试 sql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24798986/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com