Unit Tests
http://wiki.developerforce.com/page/An_Introduction_to_Apex_Code_Test_Methods
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content%2Fapex_testing.htm
http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content%2Fapex_testing.htm
Apex Unit Tests
The test method
exercises and validates the code in the trigger and class to test and verify
code coverage.
This class is defined using the @isTest
annotation
Testing is an important part of the
development process. Before you can deploy Apex or package it for the
Force.com AppExchange, the following must be true.
Unit test methods take no arguments,
commit no data to the database, and are flagged with
the testMethod keyword in the method definition.
You must have 75% test coverage to be
able to deploy your Apex code to your production organization.
Note
the following.
Test data created in the test method is
automatically rolled back when the execution completes, and you don’t need to
delete any test data explicitly.
|
Defining a Test Method using the testMethod
keyword
To define an Apex method as a 'test method', simply define the method as
static
and add the keyword testMethod
. A test method can be defined in any Apex class. A test method can not be defined in an Apex trigger. (Note: Testmethods cannot be called outside of a test context.) Here's a simple example:1 | public class myClass { |
2 | static testMethod void myTest() { |
3 | // Add test method logic using System.assert(), System.assertEquals() |
4 | // and System.assertNotEquals() here. |
5 | } |
6 | } |
Defining classes of test methods with the isTest
annotation
Use the
isTest
class annotation to define classes that only contain code used for testing your application. If your test methods are contained within their own classes and the Apex class only contains test methods, it is ideal to use the isTest
annotation.
Classes defined with the
isTest
annotation do not count against your organization limit of 2 MB for all Apex code. Classes annotated with isTest
can be declared as private or pubic. They cannot be interfaces or enums either.
Here is an example of the syntax:
1 | @isTest |
2 | private class MyTest { |
3 | // Methods for testing |
4 | } |
Test.startTest/Test.stopTest
There are two additional system static methods provided by Apex. These methods,
Test.startTest
and Test.stopTest
, are used when testing governor limits. Or in other words, executing test scenarios with a larger data set.
The
Test.startTest
method marks the point in your test code when your test actually begins. Each test method is allowed to call this method only once. All of the code before this method should be used to initialize variables, populate data structures, and so on, allowing you to set up everything you need in order to run your test. After you call this method, you get a fresh set of governor limits for the remainder of the test until you call Test.stopTest
.
The
Test.stopTest
method marks the point in your test code when your test ends. Use this method in conjunction with thestartTest
method. Each test method is allowed to call this method only once. After calling this method, any post assertions are done in the original context.
These static methods allow a test method to separate the Apex resources and governor limits being used to prepare and initialize the dataset from the resources and limits used during the actual test execution.
Here is a sample test method function that uses these methods:
01 | static testMethod void verifyAccountDescriptionsWhereOverwritten(){ |
02 | // Perform our data preparation. |
03 | List <Account > accounts = new List <Account > {}; |
04 | |
05 | for (Integer i = 0 ; i < 200 ; i++){ |
06 | Account a = new Account(Name = 'Test Account ' + i); |
07 | accounts.add(a); |
08 | } |
09 |
10 | // Start the test, this changes governor limit context to |
11 | // that of trigger rather than test. |
12 | test.startTest(); |
13 | |
14 | // Insert the Account records that cause the trigger to execute. |
15 | insert accounts; |
16 | |
17 | // Stop the test, this changes limit context back to test from trigger. |
18 | test.stopTest(); |
19 | |
20 | // Query the database for the newly inserted records. |
21 | List <Account > insertedAccounts = [ SELECT Name, Description |
22 | FROM Account |
23 | WHERE Id IN :accounts]; |
24 | |
25 | // Assert that the Description fields contains the proper value now. |
26 | for (Account a : insertedAccounts){ |
27 | System .assertEquals( |
28 | 'This Account is probably left over from testing. It should probably be deleted.' , |
29 | a.Description); |
30 | } |
31 | } |
1 | trigger OverwriteTestAccountDescriptions on Account (before insert ) { |
2 | for (Account a: Trigger. new ){ |
3 | if (a.Name.toLowerCase().contains( 'test' )){ |
4 | a.Description = |
5 | 'This Account is probably left over from testing. It should probably be deleted.' ; |
6 | } |
7 | } |
8 | } |
The example above helps illustrate how to separate the test data preparation from the actual test scenario. The first step of the example creates 200 Accounts that are required for the test scenario-and inserting these 200 Account records will have them applied to the governor limits. So in order to separate the Apex resources and governor limits used during test data preparation from the actual test scenario, the example uses the
Test.startTest()
and Test.stopTest()
methods. Therefore, the Apex code executing within the startTest and stopTest methods will obtain their own Apex governor limits and resources. If the test method did not usestartTest()
and stopTest()
, the test scenario might have hit a governor limit since some of the available Apex resources (such as total number of records processed by a DML statement) were used up by data preparation steps.System.runAs()
Generally, all Apex code runs in system mode, and the permissions and record sharing of the current user are not taken into account. The system method,
System.runAs()
, lets you write test methods that change user contexts to either an existing user or a new user. All of that user's record sharing is then enforced. You can only use runAs
in a test method. The original system context is started again after all runAs()
test methods complete.
Please note that the runAs() functionality will test and verify proper data sharing and data access. But
runAs()
does not validate CRUD or Field Level Security permissions.01 | public class TestRunAs { |
02 | public static testMethod void testRunAs() { |
03 | // Setup test data |
04 | // This code runs as the system user |
05 |
06 | Profile p = [ select id from profile where name= 'Standard User' ]; |
07 | User u = new User(alias = 'standt' , email= 'standarduser@testorg.com' , |
08 | emailencodingkey= 'UTF-8' , lastname= 'Testing' , languagelocalekey= 'en_US' , |
09 | localesidkey= 'en_US' , profileid = p.Id, |
10 | timezonesidkey= 'America/Los_Angeles' , username= 'standarduser@testorg.com' ); |
11 |
12 |
13 | System .runAs(u) { |
14 | // The following code runs as user 'u' |
15 | System .debug( 'Current User: ' + UserInfo.getUserName()); |
16 | System .debug( 'Current Profile: ' + UserInfo.getProfileId()); } |
17 | // Run some code that checks record sharing |
18 | } |
19 | } |
The above test method creates a new user (with a profile of a standard user), and executes a block of code in the context of this new user.
Comments
Post a Comment