@isTest
public class TestVerifyDate {
// test when date2 is within 30 days of date1
@isTest
static void testDateWithin30Days() {
Date date1 = Date.today();
Date date2 = Date.today().addDays(10); // within 30 days
Date result = VerifyDate.CheckDates(date1, date2);
System.assertEquals(date2, result, 'Date2 is within 30 days of Date1 so it should be returned');
}
// test when date2 is not within 30 days of date1
@isTest
static void testDateNotWithin30Days() {
Date date1 = Date.today();
Date date2 = Date.today().addDays(35); // more than 30 days
Date result = VerifyDate.CheckDates(date1, date2);
Integer totalDays = Date.daysInMonth(date1.year(), date1.month());
Date lastDayOfMonth = Date.newInstance(date1.year(), date1.month(), totalDays);
System.assertEquals(lastDayOfMonth, result, 'Date2 is not within 30 days of Date1 so end of the month should be returned');
}
// test when date2 is before date1
@isTest
static void testDate2BeforeDate1() {
Date date1 = Date.today();
Date date2 = Date.today().addDays(-5); // before date1
Date result = VerifyDate.CheckDates(date1, date2);
Integer totalDays = Date.daysInMonth(date1.year(), date1.month());
Date lastDayOfMonth = Date.newInstance(date1.year(), date1.month(), totalDays);
System.assertEquals(lastDayOfMonth, result, 'Date2 is before Date1 so end of the month should be returned');
}
}
In this test class, we have three methods. The first method tests the condition where
date2 is within 30 days of date1.
The second method tests the condition where
date2 is more than 30 days away from date1, and the third method tests the condition where
date2 is before
date1. The
System.assertEquals method is used to assert that the actual result matches the expected result.
After writing your tests, be sure to run them and check the code coverage in the Developer Console or your Salesforce IDE to make sure you have achieved 100% coverage.
//Create and install a simple Apex trigger which blocks inserts and updates to any contact with a last name of “INVALIDNAME”.
//The trigger should add an error message to the contact record and prevent the record from being saved.
trigger RestrictContactByName on Contact (before insert, before update) {
//check contacts prior to insert or update for invalid data
For (Contact c : Trigger.New) {
if(c.LastName == 'INVALIDNAME') { //invalidname is invalid
c.AddError('The Last Name "'+c.LastName+'" is not allowed for DML');
}
}
}
Here is a sample Unit Test for the above trigger to achieve 100% code coverage that includes both positive and negative test cases:
@isTest
public class TestRestrictContactByName {
@isTest static void testInvalidName() {
// Arrange
Contact c = new Contact(LastName = 'INVALIDNAME', FirstName = 'Test');
// Act
Test.startTest();
Database.SaveResult sr = Database.insert(c, false);
Test.stopTest();
// Assert
System.assert(!sr.isSuccess(), 'Record should have failed to insert');
System.assertEquals('The Last Name "INVALIDNAME" is not allowed for DML', sr.getErrors()[0].getMessage(), 'Error message should match');
}
@isTest static void testValidName() {
// Arrange
Contact c = new Contact(LastName = 'VALIDNAME', FirstName = 'Test');
// Act
Test.startTest();
Database.SaveResult sr = Database.insert(c, false);
Test.stopTest();
// Assert
System.assert(sr.isSuccess(), 'Record should have inserted successfully');
}
}
//Create an Apex class that returns a list of contacts based on two incoming parameters:
//the number of contacts to generate and the last name for those contacts.
//Do not insert the contacts into the database.
//Create an Apex class in the public scope named RandomContactFactory without the @isTest annotation.
//Use a Public Static Method to consistently generate contacts with unique first names based on the iterated number in the format Test 1, Test 2, Test 3, etc.
//Method Name: generateRandomContacts without the @isTest annotation
//Parameter 1: Integer numContacts being the number of contacts to generate with unique first names
//Parameter 2: String lastName being the last name for those contacts
//Return Type: List
public class RandomContactFactory {
public static List generateRandomContacts(Integer numContacts, String lastName) {
List contacts = new List();
for (Integer i = 1; i <= numContacts; i++) {
Contact c = new Contact();
c.FirstName = 'Test ' + i;
c.LastName = lastName;
contacts.add(c);
}
return contacts;
}
}
Can we test asynchronous Apex using Salesforce Apex Test classes?
Yes, you can test asynchronous Apex code like future methods, batch Apex, and scheduled Apex.
Salesforce provides a Test method called `Test.startTest()` and `Test.stopTest()` which allows the system to execute asynchronous code synchronously for testing purposes.
When you call `Test.stopTest()`, all asynchronous processes kicked off after `Test.startTest()` are collected and executed before the test method finishes.
How can we handle test data setup for managed packages in Apex?
Test data setup for managed packages can be quite challenging, especially since the Apex SeeAllData annotation is set to false by default in order to ensure test isolation.
It means tests do not have access to pre-existing data in the organization, such as standard Salesforce objects and custom objects.
If you're developing a managed package, it's good practice to include Apex classes that provide setup methods specifically for generating test data.
These can be used by any test methods included in the package, which helps in ensuring consistency and reducing redundancy.
How does Governor Limits impact testing in Apex?
Apex tests are subjected to Governor Limits, just like non-test classes.
Salesforce enforces a number of runtime limits to ensure that runaway Apex doesn't monopolize shared resources. Tests that exceed governor limits fail.
However, the `Test.startTest()` and `Test.stopTest()` methods give you a new set of governor limits during the test execution.
Any code that is executed after the `Test.startTest()` method is subject to a fresh set of governor limits.
This can be used strategically in tests to ensure that you have enough resources to test bulk or complex operations.