Salesforce Platform Developer Practice Exam
Salesforce Certified Platform Developer
The Salesforce Certified Platform Developer exam is for developers who build custom business logic and user interfaces on the Salesforce Platform with Apex, SOQL, Lightning Web Components and Flow. It covers four sections: developer fundamentals at 27 percent, process automation and logic at 28 percent, user interface at 25 percent, and testing, debugging and deployment at 20 percent. The exam has 60 multiple-choice questions in 105 minutes and a passing score of 68 percent. This practice exam mirrors that scope with single-answer and multiple-answer questions, each with an explanation.
Question bank updated : questions, answers, explanations and chapters.
Certification Overview
- Exam name: Platform Developer
- Vendor: Salesforce
- Duration: 105 minutes
- Total questions: about 60
- Official passing score: 68% (source)
- Our practice exam pass mark: 68%
Who Should Take This Exam?
Salesforce Developer, Apex Developer, Lightning Web Components Developer, Salesforce Administrator moving into code, Salesforce Consultant, Full-Stack Developer, Technical Lead
Prerequisites
None. Anyone may take the exam; Salesforce recommends experience writing Apex and Lightning Web Components and publishes a Trailhead trailmix to prepare.
Topics Covered
- Developer Fundamentals
- Process Automation and Logic
- User Interface
- Testing, Debugging, and Deployment
Question Types
- Multiple Choice (Single Answer)
- Multiple Choice (Multiple Answers)
Platform Developer Practice Questions
Our question bank contains 645+ practice questions for this certification. Sample questions from each exam chapter. Expand a question to see the answer choices. With a subscription, you get unlimited practice exams with randomised questions from our full question bank.
Developer Fundamentals
In the Model-View-Controller pattern as applied to the Salesforce Platform, which component represents the Model?
- A. Apex classes and triggers
- B. Objects, fields and relationships Correct answer
- C. Lightning web components
- D. Lightning pages and page layouts
Option B is correct because in MVC on the Salesforce Platform the Model is the data layer: objects, fields and relationships. Apex classes and triggers (A) are the Controller, while Lightning web components (C) and Lightning pages and page layouts (D) are the View.
A Salesforce instance hosts many customers' orgs on shared hardware. Which platform mechanism keeps one tenant's runaway Apex from degrading the others?
- A. Org-wide defaults
- B. The role hierarchy
- C. Field-level security
- D. Governor limits Correct answer
Option D is correct because governor limits cap the resources (queries, DML, CPU time, heap) that any one transaction can use on the shared multitenant platform, so runaway code fails instead of starving other tenants. Org-wide defaults, the role hierarchy and field-level security (A, B, C) control data access, not resource consumption.
A developer wants a new custom UI component built on the browser's native Web Components standards, with custom elements, shadow DOM and ES modules, rather than a proprietary component model. What should the developer build?
- A. A Lightning Out app
- B. A Lightning web component Correct answer
- C. A Visualforce page
- D. An Aura component
Option B is correct because Lightning web components are built on native Web Components standards (custom elements, shadow DOM, ES modules). Aura components (D) use a proprietary framework, Visualforce (C) is a server-rendered page technology, and Lightning Out (A) is a way to host components in external apps, not a component model.
A Visualforce page lists accounts through a custom controller class. A business user asks that the list show only active accounts, sorted by name. In MVC terms, what needs to change?
- A. The Account object's field definitions
- B. The query in the Apex controller class Correct answer
- C. The page layout assigned to the user's profile
- D. The Visualforce page markup
Option B is correct because which records are returned and how they are sorted is decided by the SOQL query in the controller (the C in MVC). The object's field definitions (A) are the Model and do not change, and the page markup (D) and page layout (C) only affect how data is displayed.
A team moves an application from a dedicated-server environment to the Salesforce Platform. Which three characteristics of the multitenant architecture affect how they write and ship code? Choose 3 answers.
- A. Governor limits keep one tenant's code from using shared resources Correct answer
- B. Developers add database indexes with SQL DDL on their org's tables
- C. The query optimizer relies on tenant-specific data statistics Correct answer
- D. Each org runs Apex in its own virtual machine with private CPU and memory
- E. Apex needs minimum test coverage before it deploys to production Correct answer
Options A, C and E are correct because governor limits, tenant-aware query optimization and the 75% Apex test-coverage requirement for production deployments are all direct consequences of many orgs sharing one platform. Option B is wrong because developers cannot run SQL DDL on the underlying tables, and option D is wrong because orgs share the runtime rather than getting a private virtual machine.
Process Automation and Logic
Invoice__c is the detail side of a master-detail relationship to Account. Finance wants Account to show the total of all Amount__c values on its invoices, and the team wants the least ongoing maintenance. What should the developer implement?
- A. An Apex trigger on Invoice__c that updates Account
- B. A cross-object formula field on Account
- C. An after-save record-triggered flow on Invoice__c that updates Account
- D. A roll-up summary field on Account Correct answer
Option D is correct because a roll-up summary field natively sums Amount__c across the detail records of a master-detail relationship, with no code or automation to maintain. A trigger (A) or flow (C) would work but must be built and maintained, and a cross-object formula (B) can only look up from child to parent, not aggregate children.
A class needs an Integer named MAX_RETRIES that is assigned once, at declaration, and must not be reassigned anywhere else. Which modifier enforces that?
- A. final Correct answer
- B. virtual
- C. transient
- D. static
Option A is correct because a final variable can be assigned only once, at declaration or in a constructor/initializer, and any later reassignment is a compile error. virtual applies to classes and methods, transient excludes a field from view state serialization, and static only ties the variable to the class.
The Deal class holds a Decimal field named amount. Code calls sort() on a List<Deal>, and the deals must end up ordered by amount. What does the Deal class have to do?
- A. Implement Iterable<Deal> and return the deals in order
- B. Implement Comparable and define compareTo(Object other) Correct answer
- C. Override equals and hashCode to compare the amount
- D. Be marked virtual and override the sort() method
Option B is correct because List.sort() orders custom objects only if their class implements the Comparable interface and defines compareTo(Object), where Deal can compare the amount values. Iterable (A) is about looping, equals/hashCode (C) are for equality and Set/Map keys, and sort() cannot be overridden (D).
What is the value of total after this code runs? Integer total = 0; for (Integer i = 0; i < 5; i++) { if (i == 2) { continue; } if (i == 4) { break; } total += i; }
- A. 3
- B. 4 Correct answer
- C. 8
- D. 10
Option B is correct. The loop adds 0 and 1, skips i = 2 with continue, adds 3, then breaks at i = 4 before adding it, so total = 0 + 1 + 3 = 4. The values 3, 8 and 10 come from miscounting the continue or the break.
Invoice__c is the detail side of a master-detail relationship to Account. Which two statements about a roll-up summary field defined on Account are true? Choose 2 answers.
- A. It can return the MIN of a Currency field on the invoices Correct answer
- B. It can return the AVG of a Number field on the invoices
- C. It can be limited to invoices that meet filter criteria Correct answer
- D. It can be created on Invoice__c to summarize its Account
Options A and C are correct because a roll-up summary field supports COUNT, SUM, MIN and MAX, so MIN over a Currency field works, and it can be restricted with filter criteria so only matching detail records are included. Option B is wrong because AVG is not an available roll-up type, and option D is wrong because a roll-up summary is defined on the master (Account), never on the detail (Invoice__c).
User Interface
A Visualforce page renders a customer's free-text feedback with <apex:outputText value="{!fb.Comments__c}" escape="false"/>. Which vulnerability does this markup open up?
- A. Cross-site request forgery
- B. Session fixation
- C. Cross-site scripting (XSS) Correct answer
- D. SOQL injection
Option C is correct because escape="false" tells Visualforce to output the field without HTML-encoding it, so any script a user typed into the feedback runs in other users' browsers, which is cross-site scripting. CSRF (A) is mitigated by Visualforce's built-in form tokens, session fixation (B) is unrelated to output encoding, and SOQL injection (D) concerns queries built from input, not page rendering.
A developer wants a custom Lightning web component to be selectable as an element on a screen in Flow Builder. Which target must its js-meta.xml file list?
- A. lightning__FlowScreen Correct answer
- B. lightning__Tab
- C. lightning__RecordPage
- D. lightning__AppPage
Option A is correct because a component appears as a screen element in Flow Builder only when its js-meta.xml lists the lightning__FlowScreen target (with isExposed set to true). lightning__Tab, lightning__RecordPage and lightning__AppPage place a component on tabs, record pages and app pages, not in flow screens.
After a successful save, an LWC's handler must show a green confirmation message to the user. Which statement does that?
- A. this.template.querySelector('lightning-card').showToast('Saved', 'success');
- B. this.dispatchEvent(new ShowToastEvent({ title: 'Saved', variant: 'success' })); Correct answer
- C. this.dispatchEvent(new CustomEvent('toast', { detail: { title: 'Saved', variant: 'success' } }));
- D. ShowToastEvent.fire({ title: 'Saved', variant: 'success' });
Option B is correct because an LWC shows a toast by dispatching a ShowToastEvent imported from lightning/platformShowToastEvent; the variant 'success' gives the green style. lightning-card has no showToast method (A), a generic CustomEvent named 'toast' is not handled by the platform (C), and ShowToastEvent has no static fire() method (D).
A custom controller's save() action finds that a required value is missing and must show a message in <apex:pageMessages/>. Which statement does that?
- A. ApexPages.currentPage().getParameters().put('error', 'Name is required');
- B. throw new AuraHandledException('Name is required');
- C. ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Name is required')); Correct answer
- D. System.debug(LoggingLevel.ERROR, 'Name is required');
Option C is correct because ApexPages.addMessage adds an ApexPages.Message to the page's message collection, which apex:pageMessages renders. Putting a value in the URL parameters (A) shows nothing, AuraHandledException (B) is for Aura/LWC controllers, and System.debug (D) only writes to the debug log.
A developer reviews how Apex sharing keywords behave across classes. Which two statements are true? Choose 2 answers.
- A. A method in a without sharing class ignores sharing rules even when a with sharing class calls it Correct answer
- B. An inner class does not inherit the sharing setting of its outer class Correct answer
- C. Declaring a class with sharing also enforces the running user's object permissions and field-level security
- D. Sharing rules apply to DML in a with sharing class but not to SOQL queries
Options A and B are correct. Sharing is declared per class, so a method in a without sharing class runs without sharing rules even when a with sharing class calls it, and an inner class does not inherit the sharing setting of its outer class. Option C is wrong because with sharing enforces record-level sharing only, not object permissions or field-level security. Option D is wrong because with sharing applies to SOQL as well as DML.
Testing, Debugging, and Deployment
A test method has no setup code and runs this line in an org that holds 5,000 accounts. The class is annotated with plain @IsTest. Integer n = [SELECT COUNT() FROM Account]; What does n equal?
- A. 0 Correct answer
- B. 200
- C. 1,000
- D. 5,000
Option A is correct because a test class annotated with plain @IsTest cannot see org data; it only sees records the test itself creates, so with no setup code the Account count is 0. The 5,000 existing accounts (option D) are visible only with SeeAllData=true, and 200 and 1,000 are not values this query could return.
A test must prove that a user with no sharing access cannot see a private Account created earlier in the same test. The User record u is already inserted and the Account is held in acct. Which block runs the query as that user?
- A. System.runAs(u) { Assert.areEqual(0, [SELECT COUNT() FROM Account WHERE Id = :acct.Id]); } Correct answer
- B. UserInfo.setUser(u); Assert.areEqual(0, [SELECT COUNT() FROM Account WHERE Id = :acct.Id]);
- C. System.runAs(u.Id) { Assert.areEqual(0, [SELECT COUNT() FROM Account WHERE Id = :acct.Id]); }
- D. Test.runAs(u) { Assert.areEqual(0, [SELECT COUNT() FROM Account WHERE Id = :acct.Id]); }
Option A is correct because System.runAs(User) runs the enclosed block with that user's sharing and permissions, so the query shows what u can see. UserInfo.setUser does not exist as a way to switch context, System.runAs takes a User record rather than an Id, and there is no Test.runAs method.
A service method makes two callouts in one transaction. A GET to https://api.example.com/rates must return 200 with a JSON body, and a GET to https://api.example.com/audit must return 404. One test has to exercise both paths. Which mock setup works?
- A. Call Test.setMock once per endpoint, each time with its own StaticResourceCalloutMock
- B. Register a MultiStaticResourceCalloutMock with one static resource per endpoint and call setStatusCode(404) on it
- C. Implement HttpCalloutMock and pick the response from req.getEndpoint() in respond() Correct answer
- D. Annotate the test with @IsTest(SeeAllData=true) so the callouts reach the real endpoints
Option C is correct because a single HttpCalloutMock implementation can inspect req.getEndpoint() in respond() and return a 200 JSON response for one URL and a 404 for the other. Only one mock is active per test context, so a second Test.setMock replaces the first (option A), and a MultiStaticResourceCalloutMock applies one status code to every response (option B). Tests cannot make real callouts, and SeeAllData does not change that (option D).
A test class has one @testSetup method that inserts 50 Accounts, and three @IsTest methods. The first test method deletes every Account it can query. Which two statements about the class are true? Choose 2 answers.
- A. Setup records can be queried by the first method that runs, and by no other.
- B. The setup method runs once, not before each test method. Correct answer
- C. Every test method starts with the 50 setup Accounts. Correct answer
- D. Accounts deleted in the first method stay deleted for the other methods.
Options B and C are correct because a @testSetup method runs once for the class, and every test method then starts with its own fresh copy of that data, since each method's changes are rolled back. Option A is wrong because every test method can query the setup records, and option D is wrong because the first method's deletes are rolled back and do not carry over to the other methods.
An @AuraEnabled method ends with throw new AuraHandledException('Quota exceeded'). A test catches the exception in a variable named e and asserts on e.getMessage(). Which two statements are true? Choose 2 answers.
- A. getMessage() returns 'Script-thrown exception'. Correct answer
- B. getMessage() returns 'Quota exceeded' in the test.
- C. Calling setMessage('Quota exceeded') on the exception before throwing it fixes the text. Correct answer
- D. getMessage() returns the text once the test calls Test.stopTest().
Options A and C are correct because an AuraHandledException built with the constructor message returns the generic 'Script-thrown exception' from getMessage() unless you call setMessage() on it before throwing. Option B is wrong for that reason, and option D is wrong because Test.stopTest() has no effect on the exception message.
Free Study Guide
Read the free Salesforce Platform Developer study guide: every exam topic explained in plain English, with diagrams, exam tips and the mistakes to avoid.
More Salesforce Practice Exams
Practise with realistic mock exams to prepare for your Salesforce certification.