Apex测试类未覆盖Item Type去重for循环,求解决方法
问题:Apex去重循环无法被测试类覆盖的优化方案
我开发了一个从POS_Item__c对象获取Item Type详情的Apex类,其中getItemTypeList_Apex方法包含提取唯一Item Type的for循环逻辑。现有测试类已创建测试数据,但始终无法覆盖该去重for循环。拒绝虚假覆盖,求正确的测试类优化方案。
业务类代码
public class ItemTypeWrapper { @AuraEnabled public Id ItemTypeId ; @AuraEnabled public String ItemType; public ItemTypeWrapper(Id ItemTypeId, String ItemType) { this.ItemTypeId = ItemTypeId; this.ItemType = ItemType; } } //method to fetch details of the Item type from the sObject POS_Item__c @AuraEnabled(cacheable=true) public static List<ItemTypeWrapper> getItemTypeList_Apex() { //variable to hold the account details objAccount=getAccount(); //to fetch the profile details of the logged in user String profileName=[Select Id,Name from Profile where Id=:userinfo.getProfileId()].Name; //instance is created itemTypeResults of type List<POS_Item__c > List<POS_Item__c> itemTypeResults = new List<POS_Item__c>(); //to hold the unique Item type ids Set<Id> uniqueItemTypeIds = new Set<Id>(); //check if the profileName is salesmanager if(profileName == folioSalesManagerProfile) { //fetch the item type details for salesmanager profile where marketing only is false itemTypeResults = [SELECT Id, Type_of_Item__r.Item_Type__c,Type_of_Item__c FROM POS_Item__c WHERE Account__c=:objAccount.Id AND Active__c=true AND Item_ID__c!=null AND (Inventory_Seasonal_Program__c='Inventory' OR Inventory_Seasonal_Program__c='Both') AND Marketing_Only__c=false AND Logical_Invenory_Stock__c > 0 ORDER BY Type_of_Item__r.Item_Type__c]; } else { itemTypeResults = [SELECT Id, Type_of_Item__r.Item_Type__c,Type_of_Item__c FROM POS_Item__c WHERE Account__c=:objAccount.Id AND Active__c=true AND Item_ID__c!=null AND (Inventory_Seasonal_Program__c='Inventory' OR Inventory_Seasonal_Program__c='Both') AND Logical_Invenory_Stock__c > 0 ORDER BY Type_of_Item__r.Item_Type__c]; } //instance is created itemTypeWrappers of type List<ItemTypeWrapper> List<ItemTypeWrapper> itemTypeWrappers = new List<ItemTypeWrapper>(); //loop through the itemTypeResultsForAFacility , for each for (POS_Item__c result : itemTypeResults ) { //get the Item type record id and store it in a container itemTypeId Id itemTypeId = (Id)result.get('Type_of_Item__c'); // Check if itemTypeId does not contains in the container uniqueItemTypeIds , if yes if (!uniqueItemTypeIds.contains(itemTypeId)) { //add the ItemType to the container ItemType String ItemType = result.Type_of_Item__r.Item_Type__c; //Create a new ItemTypeWrapper instance and add it to the list. itemTypeWrappers.add(new ItemTypeWrapper(itemTypeId, ItemType)); //Add 'itemTypeId' to 'uniqueItemTypeIds' uniqueItemTypeIds.add(itemTypeId); } } //return the itemTypeWrappers System.debug('itemTypeWrappers----'+itemTypeWrappers); return itemTypeWrappers; }
现有测试类代码
@isTest public class testClass { @isTest private static void addToCartFunctionalityTestMethod () { Account testAccount=[SELECT Id FROM Account LIMIT 1]; Brand__c testBrand=[SELECT Id FROM Brand__c LIMIT 1]; Item_Type__c testItemtype=[SELECT Id FROM Item_Type__c LIMIT 1]; List<POS_Item__c> testPosItems=[SELECT Id FROM POS_Item__c]; Test.startTest(); ApexClass.getBrandList_Apex(); ApexClass.getItemTypeList_Apex(); Test.stopTest(); } @testSetup static void setupData() { List<Account> testAccts = new List<Account>(); Account acct = new Account(Name='demo'); insert acct ; Contact contact=new Contact(LastName='Testing',AccountId=acct.Id); insert contact; Profile profile=[SELECT Name FROM Profile WHERE Name='Customer Community Plus User' LIMIT 1]; User communityUser = new User(Alias = 'standt', Email='standarduser@testorg.com', EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', LocaleSidKey='en_US', ProfileId = profile.Id, TimeZoneSidKey='America/Los_Angeles', UserName='standarduser@testorg.com',ContactId=contact.Id); insert communityUser; Brand__c brand = new Brand__c (Brand_Name__c='BrandNameSelect',Active__c=true,Account__c=acct.Id); insert brand; Item_Type__c itemType= new Item_Type__c(Item_Type__c='itemTypeSelect',Active__c=true,Account__c=acct.Id); insert itemType; POS_Item__c posItem= new POS_Item__c (Item_No__c='Test-No-01',Item_Name__c='testPosItemName',Available_Stock__c=10, Account__c=acct.Id,Brand__c=brand.Id,Type_of_Item__c=itemType.Id,Active__c=true); insert posItem; POS_Item__c posItem2= new POS_Item__c (Item_No__c='Test-No-02',Item_Name__c='testPosItemName',Available_Stock__c=10, Account__c=acct.Id,Brand__c=brand.Id,Type_of_Item__c=itemType.Id,Active__c=true); insert posItem2; } }
问题根因
- 查询条件未满足:业务方法的SOQL包含
Item_ID__c!=null、Inventory_Seasonal_Program__c枚举限制、Logical_Invenory_Stock__c > 0等过滤条件,但测试数据未设置这些字段,导致查询返回空列表,循环根本未执行。 - 用户上下文未切换:测试类创建了社区用户,但未用
System.runAs切换到该用户执行测试,导致getAccount()获取的账户或Profile判断逻辑与预期不符。 - 去重逻辑未完全触发:现有测试数据仅创建了同一种Item Type的POS_Item,只能测试第一次进入判断分支的情况,无法覆盖重复Item Type时跳过的逻辑。
测试类优化方案
1. 补全测试数据的过滤字段
在setupData中给POS_Item__c补充业务方法要求的所有字段,同时创建多组不同Item Type的数据以触发去重逻辑:
@testSetup static void setupData() { // ... 原有账户、联系人、用户、品牌创建代码 ... Item_Type__c itemType= new Item_Type__c(Item_Type__c='itemTypeSelect',Active__c=true,Account__c=acct.Id); insert itemType; // 创建第一个Item Type的POS_Item,补全所有过滤字段 POS_Item__c posItem= new POS_Item__c ( Item_No__c='Test-No-01', Item_Name__c='testPosItemName', Available_Stock__c=10, Account__c=acct.Id, Brand__c=brand.Id, Type_of_Item__c=itemType.Id, Active__c=true, Item_ID__c='TEST-ID-001', // 满足Item_ID__c!=null Inventory_Seasonal_Program__c='Inventory', // 满足枚举条件 Logical_Invenory_Stock__c=5, // 满足>0条件 Marketing_Only__c=false ); insert posItem; // 创建第二个不同的Item Type Item_Type__c itemType2= new Item_Type__c(Item_Type__c='itemTypeSelect2',Active__c=true,Account__c=acct.Id); insert itemType2; POS_Item__c posItem3= new POS_Item__c ( Item_No__c='Test-No-03', Item_Name__c='testPosItemName3', Available_Stock__c=10, Account__c=acct.Id, Brand__c=brand.Id, Type_of_Item__c=itemType2.Id, Active__c=true, Item_ID__c='TEST-ID-003', Inventory_Seasonal_Program__c='Both', Logical_Invenory_Stock__c=3 ); insert posItem3; // 创建同第一个Item Type的POS_Item,测试去重跳过逻辑 POS_Item__c posItem4= new POS_Item__c ( Item_No__c='Test-No-04', Item_Name__c='testPosItemName4', Available_Stock__c=10, Account__c=acct.Id, Brand__c=brand.Id, Type_of_Item__c=itemType.Id, Active__c=true, Item_ID__c='TEST-ID-004', Inventory_Seasonal_Program__c='Inventory', Logical_Invenory_Stock__c=2 ); insert posItem4; }
2. 切换到测试用户上下文执行
在测试方法中用System.runAs切换到创建的社区用户,确保上下文匹配:
@isTest private static void getItemTypeList_Test() { User testUser = [SELECT Id FROM User WHERE UserName='standarduser@testorg.com']; Test.startTest(); System.runAs(testUser){ List<ItemTypeWrapper> result = ApexClass.getItemTypeList_Apex(); // 断言去重结果:应返回2个唯一Item Type System.assertEquals(2, result.size(), '去重后需返回2个唯一的Item Type'); } Test.stopTest(); }
3. 覆盖Sales Manager分支(可选)
若需覆盖folioSalesManagerProfile分支,需创建对应权限的测试用户并单独测试:
@testSetup static void setupData() { // ... 原有代码 ... // 创建Sales Manager用户 Profile salesManagerProfile = [SELECT Id FROM Profile WHERE Name='Sales Manager' LIMIT 1]; User salesManagerUser = new User( Alias = 'salesmgr', Email='salesmgr@testorg.com', EmailEncodingKey='UTF-8', LastName='SalesMgr', LanguageLocaleKey='en_US', LocaleSidKey='en_US', ProfileId = salesManagerProfile.Id, TimeZoneSidKey='America/Los_Angeles', UserName='salesmgr@testorg.com', ContactId=contact.Id ); insert salesManagerUser; // 创建Marketing_Only__c=true的POS_Item,测试过滤逻辑 POS_Item__c posItemMarketingOnly= new POS_Item__c ( Item_No__c='Test-No-05', Item_Name__c='testMarketingItem', Available_Stock__c=10, Account__c=acct.Id, Brand__c=brand.Id, Type_of_Item__c=itemType.Id, Active__c=true, Item_ID__c='TEST-ID-005', Inventory_Seasonal_Program__c='Inventory', Logical_Invenory_Stock__c=4, Marketing_Only__c=true ); insert posItemMarketingOnly; } @isTest private static void getItemTypeList_SalesManager_Test() { User salesManagerUser = [SELECT Id FROM User WHERE UserName='salesmgr@testorg.com']; Test.startTest(); System.runAs(salesManagerUser){ List<ItemTypeWrapper> result = ApexClass.getItemTypeList_Apex(); // 断言:MarketingOnly的Item会被过滤,仍返回2个唯一Item Type System.assertEquals(2, result.size(), 'Sales Manager需过滤Marketing Only类型的Item'); } Test.stopTest(); }
内容的提问来源于stack exchange,提问作者Kavya
相关产品推荐
相关产品推荐

