在Salesforce中编写Unit Test

Unit Test 也是一个 Class 文件,所以在创建 Unit Test 的时候要选择 Test Class 类型来创建,请看如下截图(在Eclipse中):

 

编写 Unit Test 基本流程为:

  1):创建模拟数据。  

  2):调用Test.startTest方法。

  3):调用对应的我们所测试的方法。

  4):调用Test.stopTest()方法。

 

测试代码段一般会涉及到:测试属性,测试公共方法,测试静态方法,测试trigger。 请看如下代码段:

@isTest(SeeAllData = true)
private class EricSunUtilityTest {

    static testMethod void myUnitTest() {
    
        // first - what user profile are they? Sales Rep
        Profile p = [select id from Profile where Name = 'Sales Rep' limit 1];
        system.assert(p.id != null);
        User u = [select id, territory__c from User where ProfileId =:p.id and IsActive = true and territory__c != null limit 1];
        system.assert(u.id != null);
        
        //**---------  create test data ---------------------**//
        // create test data 
        Account a1 = new Account();
        a1.Name = 'Test Account001';
        a1.BDM_Owner__c = u.id;
        a1.Type = 'Prospect';
        insert a1;
        system.assert(a1.id != null);
        
        EricSunObject__c object1 = new EricSunObject__c();
        object1.Name = 'Test Object001';
        object1.OwnerId = u.id;
        object1.MyDate = date.newinstance(2011,7,1);
        
        system.runAs(u){

            Test.startTest();
          
            Test.setCurrentPage(Page.EricSunPage);    //set which page 
            EricSunController con = new EricSunController();    //init the 
          
            integer year = EricSunController.thisYear;     //test public variable
          
            //test special account owner
            ApexPages.currentPage().getParameters().put('uId',u.id);    //set the parameter
            con.ChangeOwner();        //test public function
          
            EricSunController.MyBillins_Target_All(u.id);    //test static function (Visualforce.remoting.Manager.invokeAction --> Remote Action)
            
            insert object1;
            system.assert(object1.id != null);    //test trigger about EricSunObject__c (insert)
            
            Test.stopTest(); 
        }
    }
}

 

编写完测试代码后,如何进行测试代码运行呢?请看如下过程:

Developer Console --- Test  --- New Run --- (Run Your Selected Test)

运行完之后,我们可以在 File --- Open 中选择对应的所测试的文件,来查看Unit Test 的覆盖率。

 

或者直接在Eclipse中运行对应的Class并且查看结果

Run Test 如下图所示:

 

View Result 如下图所示:

 

 

更加具体的细节,请详看如下链接:

http://wiki.developerforce.com/page/An_Introduction_to_Apex_Code_Test_Methods 

 

这里在简单的介绍一下 system.assert 的用法:

System.assert ---> 如果条件不满足将会抛出异常,通常我们不会在Trigger和Apex class中用到,但是在对应的Test中使用此方法是一个很好的处理方式

 

 

如何对 Generate From WSDL 所生成的 Apex Class 进行Unit Test

1):Web Service 所对应的Class 

//Generated by wsdl2apex

public class ITVDataFeedService {
    public class ArrayOfNV {
        public ITVDataFeedService.NV[] NV;
        private String[] NV_type_info = new String[]{'NV','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','-1','true'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{'NV'};
    }
    public class ArrayOfFilterInfo {
        public ITVDataFeedService.FilterInfo[] FilterInfo;
        private String[] FilterInfo_type_info = new String[]{'FilterInfo','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','-1','true'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{'FilterInfo'};
    }
    public class Feed_element {
        public String FeedName;
        public ITVDataFeedService.ArrayOfFilterInfo Filters;
        public DateTime ChangedAfter;
        private String[] FeedName_type_info = new String[]{'FeedName','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','1','false'};
        private String[] Filters_type_info = new String[]{'Filters','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','1','false'};
        private String[] ChangedAfter_type_info = new String[]{'ChangedAfter','http://www.itvisions.com.au/ITVisions.WebServices/',null,'1','1','true'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{'FeedName','Filters','ChangedAfter'};
    }
    public class NV {
        public String N;
        public String V;
        private String[] N_att_info = new String[]{'N'};
        private String[] V_att_info = new String[]{'V'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{};
    }
    public class ArrayOfArrayOfNV {
        public ITVDataFeedService.ArrayOfNV[] ArrayOfNV;
        private String[] ArrayOfNV_type_info = new String[]{'ArrayOfNV','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','-1','true'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{'ArrayOfNV'};
    }
    public class ArrayOfString {
        public String[] string_x;
        private String[] string_x_type_info = new String[]{'string','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','-1','true'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{'string_x'};
    }
    public class FeedResponse_element {
        public ITVDataFeedService.ArrayOfArrayOfNV FeedResult;
        private String[] FeedResult_type_info = new String[]{'FeedResult','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{'FeedResult'};
    }
    public class FilterInfo {
        public String Name;
        public ITVDataFeedService.ArrayOfString Values;
        private String[] Name_type_info = new String[]{'Name','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','1','false'};
        private String[] Values_type_info = new String[]{'Values','http://www.itvisions.com.au/ITVisions.WebServices/',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/','true','false'};
        private String[] field_order_type_info = new String[]{'Name','Values'};
    }
    public class DataFeedSoap {
        public String endpoint_x = 'https://corp-services.jbhifi.com.au/ITVisions.Webservices/DataFeed.asmx';
        public Map<String,String> inputHttpHeaders_x;
        public Map<String,String> outputHttpHeaders_x;
        public String clientCertName_x;
        public String clientCert_x;
        public String clientCertPasswd_x;
        public Integer timeout_x;
        private String[] ns_map_type_info = new String[]{'http://www.itvisions.com.au/ITVisions.WebServices/', 'ITVDataFeedService'};
        public ITVDataFeedService.ArrayOfArrayOfNV Feed(String FeedName,ITVDataFeedService.ArrayOfFilterInfo Filters,DateTime ChangedAfter) {
            ITVDataFeedService.Feed_element request_x = new ITVDataFeedService.Feed_element();
            request_x.FeedName = FeedName;
            request_x.Filters = Filters;
            request_x.ChangedAfter = ChangedAfter;
            ITVDataFeedService.FeedResponse_element response_x;
            Map<String, ITVDataFeedService.FeedResponse_element> response_map_x = new Map<String, ITVDataFeedService.FeedResponse_element>();
            response_map_x.put('response_x', response_x);
            WebServiceCallout.invoke(
              this,
              request_x,
              response_map_x,
              new String[]{endpoint_x,
              'http://www.itvisions.com.au/ITVisions.WebServices/Feed',
              'http://www.itvisions.com.au/ITVisions.WebServices/',
              'Feed',
              'http://www.itvisions.com.au/ITVisions.WebServices/',
              'FeedResponse',
              'ITVDataFeedService.FeedResponse_element'}
            );
            response_x = response_map_x.get('response_x');
            return response_x.FeedResult;
        }
    }
}
View Code

 

2):Unit Test

@isTest
private with sharing class ITVDataFeedServiceTest {

    static testMethod void coverTypes() {
        // query for a test user
        User u = [select id from User where id =: UserInfo.getUserId() limit 1];
        system.assert(u.id != null);
        
        // run test as current test user
        system.runAs(u){
        
            // start test
            Test.startTest();
            
            // cover inner class
            new ITVDataFeedService.ArrayOfNV();
            new ITVDataFeedService.ArrayOfFilterInfo();
            new ITVDataFeedService.Feed_element();
            new ITVDataFeedService.NV();
            new ITVDataFeedService.ArrayOfArrayOfNV();
            new ITVDataFeedService.ArrayOfString();
            new ITVDataFeedService.FeedResponse_element();
            new ITVDataFeedService.FilterInfo();
            new ITVDataFeedService.DataFeedSoap();
              
            // end test
            Test.stopTest();
        }
    }
    
    static testMethod void coverMethods()
    {
        // query for a test user
        User u = [select id from User where id =: UserInfo.getUserId() limit 1];
        system.assert(u.id != null);
        
        // run test as current test user
        system.runAs(u){
        
            // start test
            Test.startTest();
            
            // cover method
            new ITVDataFeedService.DataFeedSoap().Feed(null, null, null);
              
            // end test
            Test.stopTest();
        }
    }
    
    private class WebServiceMockImpl implements WebServiceMock
    {
        public void doInvoke(
            Object stub, Object request, Map<String, Object> response,
            String endpoint, String soapAction, String requestName,
            String responseNS, String responseName, String responseType)
        {
            if(request instanceof ITVDataFeedService.Feed_element)
                response.put('response_x', new ITVDataFeedService.FeedResponse_element());
            return;
        }
    }
    
}
View Code

 

如何对调用 Web Service 中某些方法的 Apex Class 进行 Unit Test 

1):调用Web Service的Apex Class

public class CreditLimitController {
    //added an instance varaible for the standard controller
    private ApexPages.StandardController controller {get; set;}
    // the actual account
    private Account a;
    
    public CreditLimitInfo creLimitInfo {get; set;}
    
    private string feedName = 'CustomerCredit';
    private string filterInfoName = 'CustomerID';
    private ITVDataFeedService itvDFService = new ITVDataFeedService();
    private ITVDataFeedService.DataFeedSoap dfSoap = new ITVDataFeedService.DataFeedSoap();
    
    private ITVDataFeedService.FilterInfo fInfo = new ITVDataFeedService.FilterInfo();
    private ITVDataFeedService.ArrayOfFilterInfo filterInfoArray = new ITVDataFeedService.ArrayOfFilterInfo();
    private ITVDataFeedService.ArrayOfString sArray = new ITVDataFeedService.ArrayOfString();
   
    
    
    public CreditLimitController(ApexPages.StandardController controller) {
        //initialize the stanrdard controller
        this.controller = controller;
        this.a = (Account)controller.getRecord();
        this.creLimitInfo = getCreditLimitInfo(this.a);
    }
    
    public CreditLimitInfo getCreditLimitInfo(Account acc) {
        // call web service to get the credit limit by account id
        fInfo.Name = filterInfoName;
        
        string customerId = getCustomerId(acc);
        string[] sArr = new string[] { customerId };
        sArray.string_x = sArr;
        
        fInfo.Values = sArray;
        
        filterInfoArray.FilterInfo = new ITVDataFeedService.FilterInfo[] {fInfo};
        
        ITVDataFeedService.ArrayOfArrayOfNV nvArrayArray = dfSoap.Feed(feedName, filterInfoArray, DateTime.now());

        CreditLimitInfo currentCreditLimitInfo = new CreditLimitInfo();
        if(nvArrayArray != null && nvArrayArray.ArrayOfNV != null){
            for(ITVDataFeedService.ArrayOfNV aNv : nvArrayArray.ArrayOfNV){
                for(ITVDataFeedService.NV nv : aNv.NV){
                    if(nv.N == 'CustomerID'){
                        currentCreditLimitInfo.CustomerId = nv.V;
                    }
                    else if(nv.N == 'CreditLimit'){
                        currentCreditLimitInfo.CreditLimit = Decimal.valueOf(nv.V);
                    }
                    else if(nv.N == 'AvailableCredit'){
                        currentCreditLimitInfo.AvailableCredit = Decimal.valueOf(nv.V);
                    }
                    else if(nv.N == 'Balance'){
                        currentCreditLimitInfo.Balance = Decimal.valueOf(nv.V);
                    }
                }
            }
        }
        return currentCreditLimitInfo;
    }
    
    private string getCustomerId(Account acc){
        string customerId = '';
        if(acc != null && acc.Id != null){
            List<Account> accList = [Select AccountNumber From Account Where Id =: acc.Id];
            if(accList != null && accList.size() > 0){
                customerId = accList[0].AccountNumber;
            }
        }
        return customerId;
    }
    
    public class CreditLimitInfo {
        public string CustomerId {get;set;}
        public decimal CreditLimit {get;set;}
        public decimal AvailableCredit {get;set;}
        public decimal Balance {get;set;}
        
        public CreditLimitInfo(){
          CustomerId = '';
          CreditLimit = 0;
          AvailableCredit = 0;
          Balance = 0;
        }
        
        public CreditLimitInfo(string cusId, decimal creLimit, decimal avaCredit, decimal bal){
          CustomerId = cusId;
          CreditLimit = creLimit;
          AvailableCredit = avaCredit;
          Balance = bal;
        }
     }
}
View Code

 

2):Unit Test

@isTest
private class CreditLimitControllerTest {

    static testMethod void myUnitTest() {
        // query for a test user
        User u = [select id from User where id =: UserInfo.getUserId() limit 1];
        system.assert(u.id != null);
        
        // insert test data
        Account account001 = new Account(
            Name = 'Test Account 0101',
            AccountNumber = 'IN1200047',
            Credit_Type__c = 'Account'
        );
        insert account001;
        system.assert(account001.id != null);
        
        // run test as current test user
        system.runAs(u){
        
            // start test
            Test.startTest();
            
            // This causes a fake response to be generated
              Test.setMock(WebServiceMock.class, new WebServiceMockImpl());
              
              
            Test.setCurrentPage(Page.CreditLimit);
            ApexPages.StandardController sc = new ApexPages.StandardController(account001);

              CreditLimitController con = new CreditLimitController(sc);
              
              // test the constructor contains multiple parameters
              CreditLimitController.CreditLimitInfo testCLI = new CreditLimitController.CreditLimitInfo('111', 1111.00, 1111.00, 1111.00);
            
            // end test
            Test.stopTest();
        }
    }
    
    
    private class WebServiceMockImpl implements WebServiceMock
    {
        public void doInvoke(
            Object stub, Object request, Map<String, Object> response,
            String endpoint, String soapAction, String requestName,
            String responseNS, String responseName, String responseType)
        {
            if(request instanceof ITVDataFeedService.Feed_element){
                // generate the fake data to test
                ITVDataFeedService.FeedResponse_element feedRes = new ITVDataFeedService.FeedResponse_element();
                ITVDataFeedService.ArrayOfArrayOfNV aaOfNV = new ITVDataFeedService.ArrayOfArrayOfNV();
                 
                ITVDataFeedService.ArrayOfNV aOfNV = new ITVDataFeedService.ArrayOfNV();
                
                ITVDataFeedService.NV nvCustomerID = new ITVDataFeedService.NV();
                nvCustomerID.N = 'CustomerID';
                nvCustomerID.V = 'IN1200047';
                
                ITVDataFeedService.NV nvCreditLimit = new ITVDataFeedService.NV();
                nvCreditLimit.N = 'CreditLimit';
                nvCreditLimit.V = '1000.11';
                
                ITVDataFeedService.NV nvAvailableCredit = new ITVDataFeedService.NV();
                nvAvailableCredit.N = 'AvailableCredit';
                nvAvailableCredit.V = '1000.11';
                
                ITVDataFeedService.NV nvBalance = new ITVDataFeedService.NV();
                nvBalance.N = 'Balance';
                nvBalance.V = '1000.11';
                
                ITVDataFeedService.NV[] nvArray = new ITVDataFeedService.NV[] { nvCustomerID, nvCreditLimit, nvAvailableCredit, nvBalance };
                
                aOfNV.NV = nvArray;
                
                ITVDataFeedService.ArrayOfNV[] aOfNVArray = new ITVDataFeedService.ArrayOfNV[] { aOfNV };
                
                aaOfNV.ArrayOfNV = aOfNVArray;
                
                feedRes.FeedResult = aaOfNV;
                
                // set the fake data to response
                response.put('response_x', feedRes);
            }
        }
    }
}
View Code

 

更多详细信息请看如下链接:

http://andyinthecloud.com/2013/05/11/code-coverage-for-wsdl2apex-generated-classes/ 

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex_testing.htm

 

如何对Salesforce提供的Restful Service所对应的Apex Class 进行 Unit Test, 请看如下链接:

http://salesforce.stackexchange.com/questions/4988/writing-test-classes-for-apex-restservice

还有一种偷懒的方式 请看: http://sfdc.arrowpointe.com/2009/05/01/testing-http-callouts/

 

如何对调用External Restful Service的Apex Class 进行 Unit Test, 请看如下链接:

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_restful_http_testing_httpcalloutmock.htm 

 

posted @ 2013-11-12 10:04  Eric Sun  阅读(1875)  评论(0编辑  收藏  举报