Last active
January 6, 2017 13:54
-
-
Save codefriar/16ffb954983389cf320ea92fcb3d7a01 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public with sharing class ExampleCode { | |
public class exampleCodeException extends Exception {} | |
Public Integer add(Integer one, Integer two){ | |
return one + two; | |
} | |
Public Decimal divide(Integer one, Integer two){ | |
if(two == 0){ | |
throw new exampleCodeException('Dividing by Zero makes Astro Cry'); | |
} | |
return one / two; | |
} | |
Public Decimal getBankAccount(Account a){ | |
return a.SuperSecretBankAccountNum__c; | |
} | |
Public Decimal getBankAccountThrowsException(Account a){ | |
if(a.SuperSecretBankAccountNum__c == null){ | |
throw new exampleCodeException('User has no access to this field'); | |
} | |
return a.SuperSecretBankAccountNum__c; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Created by kpoorman on 9/22/16. | |
* This example test class demonstrates best practices for unit testing in the following scenarios: | |
* * Postive Unit tests where valid input results in valid output | |
* * Negative Unit tests where invalid input correctly results in the proper exception being thrown | |
* * User permission Positive and Negative tests | |
* | |
* Prerequisites: | |
* In order for these tests to pass, the following metadata must be in the org. | |
* * a custom field, 'SuperSecretBankAccountNum__c' that is a number(18,0) field on Account | |
* * two custom profiles: 'Trailblazer' and 'Sith' | |
* ** Trailblazer should have permission to see SuperSecretBankAccountNum__c | |
* ** Sith should not | |
* * Additionally, you'll need to install the epically awesome TestFactory from here: https://github.com/dhoechst/Salesforce-Test-Factory | |
*/ | |
@IsTest | |
private class ExampleCode_Tests { | |
// Positive Test - Valid input results in valid results. | |
@isTest static void test_Add_Postive() { | |
// TEST SETUP | |
// No sObjects are needed to test this code. we'll be using hardcoded Integers. | |
exampleCode astro = new exampleCode(); | |
// Call Test.startTest() to reset governor limits and isolate the code being tested. | |
Test.startTest(); | |
// Invoke the code being tested, | |
Integer testValue = astro.add(5,7); | |
// Call Test.stopTest() to end the isolation of the tested code and re-establish governor limits. | |
Test.stopTest(); | |
// Make an Assertion to verify that our valid input of 5 and 7, resulted in a correct response of 12. | |
// Note that this assertEquals has a third parameter, a string that provides a useful developer message | |
// about what was expected and what was returned. | |
System.assertEquals(12, testValue, 'Expected 5+7 to equal 12'); | |
} | |
// Positive unit test for divide method. Given a valid set of integers, the result should be 1/1 | |
@isTest static void test_Divide_Positive() { | |
//Create Test data and objects | |
exampleCode Cloudy = new exampleCode(); | |
// Call Test.StartTest to isolate the code being tested. | |
Decimal result; | |
Test.startTest(); | |
// Call our code with bad data that *should* cause an exception to occur. | |
result = Cloudy.divide(1, 1); | |
// Call Test.stopTest() to end the isolation of the tested code and re-establish governor limits. | |
Test.stopTest(); | |
// Assert that the boolean is true, and leave a friendly developer message. | |
System.assertEquals(result, 1.0, 'Expected 1 divided by 1 to be 1'); | |
} | |
// Negative Unit test - Tests that Exceptions are thrown when bad data is passed into the Unit | |
// In this case, we're verifying that a divide by zero error is prevented and a custom exception | |
// is thrown. | |
@isTest static void test_Divide_Negative() { | |
//Create Test data and objects | |
exampleCode Reid = new exampleCode(); | |
// Create a boolean to track whether or not an exception was caught. | |
Boolean didCatchProperException = false; | |
// Call Test.StartTest to isolate the code being tested. | |
Test.startTest(); | |
// Wrap the tested code execution in a try/catch so that we can *catch* the exception we expect | |
Try { | |
// Call our code with bad data that *should* cause an exception to occur. | |
Reid.divide(1, 0); | |
// Here we catch the exact type of exception we expect the code to have thrown. | |
} catch (ExampleCode.ExampleCodeException AwesomeException){ | |
// if the proper exception was caught, then we set our boolean as true; | |
didCatchProperException = true; | |
} | |
// Call Test.stopTest() to end the isolation of the tested code and re-establish governor limits. | |
Test.stopTest(); | |
// Assert that the boolean is true, and leave a friendly developer message. | |
System.assert(didCatchProperException, 'Expected code to throw an ExampleCode.ExampleCodeException when divisor is 0'); | |
} | |
// A user permission test follows the Positive or Negative pattern, but runs the code as a user | |
// with a specific set of perissions (perm set or profile based); | |
// in this test we' | |
@isTest static void test_UserProfileHasAccessToGetBankAccount_Positive() { | |
//Create Test data and objects | |
exampleCode exCodeMachina = new exampleCode(); | |
// generate a user for testing this code. in this case we're creating a user with a given profile | |
User u = getUserWithProfile('Standard User'); | |
// Also create an Account. In this case I'm using the test factory. | |
Account a = (Account)TestFactory.createSObject(new Account()); | |
// set the bank account number to a known state. | |
a.SuperSecretBankAccountNum__c = 1234567890; | |
// Create a decimal result. | |
Decimal result; | |
// This is the crucial part for a user permission test. | |
// System.runAs runs the code inside it's block as the user thats passed in. In this case | |
// we'll be running the code with the user we created above with the profile 'Standard User' | |
System.runAs(u){ | |
// We'll start the test here | |
Test.startTest(); | |
// Execute the unit of code. | |
result = exCodeMachina.getBankAccount(a); | |
// Stop the test. | |
Test.stopTest(); | |
} | |
// Make the assertion that it's working correctly. | |
System.assertEquals(result, 1234567890, 'Expected this Trailblazers to have access to bank # by profile'); | |
} | |
// This is another example of a positive test, but in this case we're counting on the user not having access | |
// to the field in question -- this results in a NULL value for the field. | |
@isTest static void UserProfileHas_No_AccessToGetBankAccount_Positive() { | |
exampleCode exCodeMachina = new exampleCode(); | |
User u = getUserWithProfile('Chatter Free User'); | |
Account a = (Account)TestFactory.createSObject(new Account()); | |
Decimal result; | |
System.runAs(u){ | |
Test.startTest(); | |
result = exCodeMachina.getBankAccount(a); | |
Test.stopTest(); | |
} | |
System.assertEquals(result, null, 'Expected Sith lords to be blocked'); | |
} | |
// In this negative test we'll be calling a different method, one we've coded to throw an error rather than a null value. | |
// Notice how it follows the general pattern for negative unit tests with the addition of running as a user. | |
@IsTest static void UserProfileHas_No_AccessToGetBankAccount_Negative() { | |
// generate a user for testing this code. in this case we're creating a user with a given profile | |
User u = getUserWithProfile('Chatter Free User'); | |
// Also create an Account. In this case I'm using the test factory. | |
Account a = (Account)TestFactory.createSObject(new Account()); | |
// set the bank account number to a known state. | |
a.SuperSecretBankAccountNum__c = 1234567890; | |
insert a; | |
Boolean ProperExceptionCaught; | |
// We'll start the test here | |
Test.startTest(); | |
exampleCode exCodeMachina = new exampleCode(); | |
exCodeMachina.getBankAccountThrowsException(a); | |
System.runAs(u){ | |
Try { | |
//Create Test data and objects | |
exCodeMachina.getBankAccountThrowsException(a); | |
} Catch(ExampleCode.ExampleCodeException e){ | |
if(e.getMessage() == 'User has no access to this field'){ | |
ProperExceptionCaught = true; | |
} | |
} | |
} | |
// Stop the test. | |
Test.stopTest(); | |
// Make the assertion that it's working correctly. | |
// System.assert(ProperExceptionCaught, 'Expected this Trailblazers to have access to bank # by profile'); | |
} | |
// Helper methods that would normally live in their own class but are here for example sake. | |
private static User getUserWithProfile(String profileName){ | |
Integer uniq = Crypto.getRandomInteger(); | |
User u = new User( | |
ProfileId = [SELECT Id FROM Profile WHERE Name = :profileName].Id, | |
LastName = 'last' + uniq , | |
Email = 'testUser'+uniq+'@example.com', | |
Username = 'testUser'+uniq+'@example.com', | |
CompanyName = 'TEST', | |
Title = 'title', | |
Alias = 'alias', | |
TimeZoneSidKey = 'America/Los_Angeles', | |
EmailEncodingKey = 'UTF-8', | |
LanguageLocaleKey = 'en_US', | |
LocaleSidKey = 'en_US'); | |
insert u; | |
return u; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment