如何将Callable返回值作为参数传入其所在的同一个logTimes方法
问题根因
你目前实现的问题出在参数求值时机:logTimes方法的入参String... testData是在方法调用前完成求值的,你传入的dest.get()执行时对应的Callable还没有运行,AtomicReference还未赋值,所以写入数据库的对应字段自然为null。而你最终能拿到正确返回值,是因为你是在Callable执行完成后才调用返回值的get()方法,此时AtomicReference已经完成赋值,二者执行时机完全不同。
解决方案
推荐通过重载logTimes方法实现需求,不影响原有逻辑的同时支持传入执行完成后才能获取的参数:
第一步:重载logTimes方法
新增支持传入返回值处理函数的重载实现:
import java.util.Arrays; import java.util.function.Function; public static <T> T logTimes(Callable<T> callable, String actionToTest, Function<T, String[]> extraTestDataSupplier, String... baseTestData) throws Exception { LocalDateTime before = null; T result = null; try { before = LocalDateTime.now(); result = callable.call(); // Callable执行完成后,再拼接需要从返回值提取的参数 String[] finalTestData = baseTestData; if (extraTestDataSupplier != null) { String[] extraParams = extraTestDataSupplier.apply(result); finalTestData = Arrays.copyOf(baseTestData, baseTestData.length + extraParams.length); System.arraycopy(extraParams, 0, finalTestData, baseTestData.length, extraParams.length); } logToDocument(before, LocalDateTime.now(), actionToTest, finalTestData); } catch (TimeoutException ex) { logToDocument(before, LocalDateTime.now(), actionToTest, baseTestData); throw ex; // 保留原有异常抛出逻辑,上层可以正常捕获 } return result; }
第二步:修改loadedPageName方法调用逻辑
简化原有实现,无需再用AtomicReference中转:
public static String loadedPageName(WebDriver driver, int seconds) throws Exception { String originPage = pageName(driver); By loadingBar = By.xpath("//div[contains(@class, 'progress')]"); WebDriverWait w = new WebDriverWait(driver, seconds); Function<WebDriver, Boolean> pageFinishedLoading = wd -> wd.findElements(loadingBar).size() == 0; try { return ExtentTestManager.logTimes(() -> { w.until(ExpectedConditions.presenceOfAllElementsLocatedBy(loadingBar)); w.until(pageFinishedLoading); // 直接返回页面名称即可 return driver.findElement(By.tagName("body")).getAttribute("page-name"); }, REDIRECT, // 传入处理函数,执行完成后用返回值拼接参数 pageName -> new String[]{ORIGIN, originPage, DESTINATION, pageName}); } catch (TimeoutException ex) { ExtentTestManager.reporterLog("Timeout after waiting ".concat(String.valueOf(seconds)).concat(" seconds for a page to load")); ExtentTestManager.logToDocument(LocalDateTime.now(), seconds, REDIRECT, ORIGIN, originPage, DESTINATION, "timeout"); return null; } }
该方案既保留了原有logTimes的时长统计能力,也能正确将Callable的返回值作为参数写入数据库。
内容的提问来源于stack exchange,提问作者Mattemingda
相关产品推荐
相关产品推荐

