如何基于映射列表返回Iterator<Object[]>?附TestNG实现代码
Let's break down the issue in your current code first, then walk through the fix to get the behavior you want.
The Problem with Your Current Code
Your existing code creates one single HashMap instance outside the for loop. Every iteration just updates the same map's values and adds it to the list. Since you're adding a reference to the same map each time, all entries in listings end up pointing to the final state of that single map. If you uncomment listing.clear(), all entries would become empty maps entirely—definitely not what you want.
The Fix: Create a New Map Per Iteration
To get three distinct maps (each with its own category, usage, and country values), you need to instantiate a new HashMap inside the for loop. This ensures every entry in your list is an independent object.
Here's the corrected code that returns an Iterator<Object[]> as you requested:
@DataProvider(name = "NewListings") public Iterator<Object[]> AddNewListings(){ List<Map<String,String>> listings = new ArrayList<>(); Random rand = new Random(); // Create a new Map for each iteration for (int i = 0; i < 3; i++){ Map<String,String> listing = new HashMap<>(); listing.put("category", Integer.toString(rand.nextInt(8) + 1)); listing.put("usage", Integer.toString(rand.nextInt(8) + 1)); listing.put("country", Integer.toString(rand.nextInt(8) + 1)); listings.add(listing); } // Convert the list of maps to an Iterator<Object[]> using streams (cleaner than loops) return listings.stream() .map(map -> new Object[]{map}) .iterator(); } @Test(dataProvider = "NewListings") public void addListing(Map<String, String> field){ // Now each test run gets a unique map with all three fields // Example usage: System.out.println("Category: " + field.get("category")); System.out.println("Usage: " + field.get("usage")); System.out.println("Country: " + field.get("country")); // do your actual test logic here }
If You Prefer Returning Object[][] Instead
TestNG also accepts Object[][] as a DataProvider return type. Here's how to adjust the code for that:
@DataProvider(name = "NewListings") public Object[][] AddNewListings(){ List<Map<String,String>> listings = new ArrayList<>(); Random rand = new Random(); for (int i = 0; i < 3; i++){ Map<String,String> listing = new HashMap<>(); listing.put("category", Integer.toString(rand.nextInt(8) + 1)); listing.put("usage", Integer.toString(rand.nextInt(8) + 1)); listing.put("country", Integer.toString(rand.nextInt(8) + 1)); listings.add(listing); } // Convert list to Object[][] using streams return listings.stream() .map(map -> new Object[]{map}) .toArray(Object[][]::new); }
Key Takeaways
- Always create a new data object (in this case, a
HashMap) inside your loop when building test data—this prevents reference sharing and data overwrites. - TestNG supports both
Iterator<Object[]>andObject[][]for DataProviders; pick whichever fits your code style better. - Java Streams make converting collections to the required DataProvider format much cleaner than manual loops.
内容的提问来源于stack exchange,提问作者gmitsios

