diff --git a/CRM/Contribute/BAO/ContributionSoft.php b/CRM/Contribute/BAO/ContributionSoft.php
index 40fe273e22c516793d5705a67d8bb2f7d4d62188..670e30adfae7f030edea4e73c9f6725024b60013 100644
--- a/CRM/Contribute/BAO/ContributionSoft.php
+++ b/CRM/Contribute/BAO/ContributionSoft.php
@@ -53,39 +53,17 @@ class CRM_Contribute_BAO_ContributionSoft extends CRM_Contribute_DAO_Contributio
    * Process the soft contribution and/or link to personal campaign page.
    *
    * @param array $params
-   * @param object $contribution CRM_Contribute_DAO_Contribution
+   * @param CRM_Contribute_BAO_Contribution $contribution
    *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
    */
   public static function processSoftContribution($params, $contribution) {
-    //retrieve existing soft-credit and pcp id(s) if any against $contribution
-    $softIDs = self::getSoftCreditIds($contribution->id);
-    $pcpId = self::getSoftCreditIds($contribution->id, TRUE);
-
-    if ($pcp = CRM_Utils_Array::value('pcp', $params)) {
-      $softParams = [];
-      $softParams['id'] = $pcpId ? $pcpId : NULL;
-      $softParams['contribution_id'] = $contribution->id;
-      $softParams['pcp_id'] = $pcp['pcp_made_through_id'];
-      $softParams['contact_id'] = CRM_Core_DAO::getFieldValue('CRM_PCP_DAO_PCP',
-        $pcp['pcp_made_through_id'], 'contact_id'
-      );
-      $softParams['currency'] = $contribution->currency;
-      $softParams['amount'] = $contribution->total_amount;
-      $softParams['pcp_display_in_roll'] = $pcp['pcp_display_in_roll'] ?? NULL;
-      $softParams['pcp_roll_nickname'] = $pcp['pcp_roll_nickname'] ?? NULL;
-      $softParams['pcp_personal_note'] = $pcp['pcp_personal_note'] ?? NULL;
-      $softParams['soft_credit_type_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_ContributionSoft', 'soft_credit_type_id', 'pcp');
-      $contributionSoft = self::add($softParams);
-      //Send notification to owner for PCP
-      if ($contributionSoft->pcp_id && empty($pcpId)) {
-        CRM_Contribute_Form_Contribution_Confirm::pcpNotifyOwner($contribution, $contributionSoft);
-      }
-    }
-    //Delete PCP against this contribution and create new on submitted PCP information
-    elseif (array_key_exists('pcp', $params) && $pcpId) {
-      civicrm_api3('ContributionSoft', 'delete', ['id' => $pcpId]);
+    if (array_key_exists('pcp', $params)) {
+      self::processPCP($params['pcp'], $contribution);
     }
     if (isset($params['soft_credit'])) {
+      $softIDs = self::getSoftCreditIds($contribution->id);
       $softParams = $params['soft_credit'];
       foreach ($softParams as $softParam) {
         if (!empty($softIDs)) {
@@ -602,4 +580,42 @@ class CRM_Contribute_BAO_ContributionSoft extends CRM_Contribute_DAO_Contributio
     }
   }
 
+  /**
+   * Process the pcp associated with a contribution.
+   *
+   * @param array $pcp
+   * @param \CRM_Contribute_BAO_Contribution $contribution
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   */
+  protected static function processPCP($pcp, $contribution) {
+    $pcpId = self::getSoftCreditIds($contribution->id, TRUE);
+
+    if ($pcp) {
+      $softParams = [];
+      $softParams['id'] = $pcpId ?: NULL;
+      $softParams['contribution_id'] = $contribution->id;
+      $softParams['pcp_id'] = $pcp['pcp_made_through_id'];
+      $softParams['contact_id'] = CRM_Core_DAO::getFieldValue('CRM_PCP_DAO_PCP',
+        $pcp['pcp_made_through_id'], 'contact_id'
+      );
+      $softParams['currency'] = $contribution->currency;
+      $softParams['amount'] = $contribution->total_amount;
+      $softParams['pcp_display_in_roll'] = $pcp['pcp_display_in_roll'] ?? NULL;
+      $softParams['pcp_roll_nickname'] = $pcp['pcp_roll_nickname'] ?? NULL;
+      $softParams['pcp_personal_note'] = $pcp['pcp_personal_note'] ?? NULL;
+      $softParams['soft_credit_type_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_ContributionSoft', 'soft_credit_type_id', 'pcp');
+      $contributionSoft = self::add($softParams);
+      //Send notification to owner for PCP
+      if ($contributionSoft->pcp_id && empty($pcpId)) {
+        CRM_Contribute_Form_Contribution_Confirm::pcpNotifyOwner($contribution, $contributionSoft);
+      }
+    }
+    //Delete PCP against this contribution and create new on submitted PCP information
+    elseif ($pcpId) {
+      civicrm_api3('ContributionSoft', 'delete', ['id' => $pcpId]);
+    }
+  }
+
 }
diff --git a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php
index 12647109169d263aa3767d5f76c410197c228f2b..3ab9be1c36013b005542c678be3f31819c56b5ca 100644
--- a/tests/phpunit/CRM/Contribute/Form/ContributionTest.php
+++ b/tests/phpunit/CRM/Contribute/Form/ContributionTest.php
@@ -17,6 +17,7 @@
  * @group headless
  */
 class CRM_Contribute_Form_ContributionTest extends CiviUnitTestCase {
+  use CRMTraits_PCP_PCPTestTrait;
 
   protected $_individualId;
   protected $_contribution;
@@ -80,7 +81,7 @@ class CRM_Contribute_Form_ContributionTest extends CiviUnitTestCase {
     parent::setUp();
     $this->_userId = $this->createLoggedInUser();
 
-    $this->_individualId = $this->individualCreate();
+    $this->_individualId = $this->ids['contact'][0] = $this->individualCreate();
     $this->_params = [
       'contact_id' => $this->_individualId,
       'receive_date' => '20120511',
@@ -809,6 +810,32 @@ Price Field - Price Field 1        1   $ 100.00      $ 100.00
     $mut->stop();
   }
 
+  /**
+   * Test submitting the back office contribution form with pcp data.
+   *
+   * @throws \CRM_Core_Exception
+   * @throws \CiviCRM_API3_Exception
+   * @throws \Civi\Payment\Exception\PaymentProcessorException
+   */
+  public function testSubmitWithPCP() {
+    $params = $this->pcpParams();
+    $pcpID = $this->createPCPBlock($params);
+    $form = new CRM_Contribute_Form_Contribution();
+    $form->testSubmit([
+      'financial_type_id' => 3,
+      'contact_id' => $this->_individualId,
+      'payment_instrument_id' => CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'payment_instrument_id', 'Check'),
+      'contribution_status_id' => 1,
+      'total_amount' => 5,
+      'pcp_made_through_id' => $pcpID,
+      'pcp_display_in_roll' => '1',
+      'pcp_roll_nickname' => 'Dobby',
+      'pcp_personal_note' => 'I wuz here',
+    ], CRM_Core_Action::ADD);
+    $softCredit = $this->callAPISuccessGetSingle('ContributionSoft', []);
+    $this->assertEquals('Dobby', $softCredit['pcp_roll_nickname']);
+  }
+
   /**
    * Test the submit function on the contribution page.
    */
diff --git a/tests/phpunit/CRM/PCP/BAO/PCPTest.php b/tests/phpunit/CRM/PCP/BAO/PCPTest.php
index adfe01f2bae43904014480a5cabe65d74c73b9b5..267b33d5db133676eebae0fa3bd779968d27d795 100644
--- a/tests/phpunit/CRM/PCP/BAO/PCPTest.php
+++ b/tests/phpunit/CRM/PCP/BAO/PCPTest.php
@@ -45,26 +45,15 @@ class CRM_PCP_BAO_PCPTest extends CiviUnitTestCase {
     $this->assertEquals($params['is_active'], $pcpBlock->is_active, 'Check for is_active.');
   }
 
-  public function testAddPCP() {
-    $blockParams = $this->pcpBlockParams();
-    $pcpBlock = CRM_PCP_BAO_PCPBlock::create($blockParams);
-
+  /**
+   * Basic create test.
+   *
+   * @throws \CRM_Core_Exception
+   */
+  public function testCreatePCP() {
     $params = $this->pcpParams();
-    $params['pcp_block_id'] = $pcpBlock->id;
-
-    $pcp = CRM_PCP_BAO_PCP::create($params);
-
-    $this->assertInstanceOf('CRM_PCP_DAO_PCP', $pcp, 'Check for created object');
-    $this->assertEquals($params['contact_id'], $pcp->contact_id, 'Check for entity table.');
-    $this->assertEquals($params['status_id'], $pcp->status_id, 'Check for status.');
-    $this->assertEquals($params['title'], $pcp->title, 'Check for title.');
-    $this->assertEquals($params['intro_text'], $pcp->intro_text, 'Check for intro_text.');
-    $this->assertEquals($params['page_text'], $pcp->page_text, 'Check for page_text.');
-    $this->assertEquals($params['donate_link_text'], $pcp->donate_link_text, 'Check for donate_link_text.');
-    $this->assertEquals($params['is_thermometer'], $pcp->is_thermometer, 'Check for is_thermometer.');
-    $this->assertEquals($params['is_honor_roll'], $pcp->is_honor_roll, 'Check for is_honor_roll.');
-    $this->assertEquals($params['goal_amount'], $pcp->goal_amount, 'Check for goal_amount.');
-    $this->assertEquals($params['is_active'], $pcp->is_active, 'Check for is_active.');
+    $pcpID = $this->createPCPBlock($params);
+    $this->getAndCheck($params, $pcpID, 'Pcp');
   }
 
   public function testAddPCPNoStatus() {
diff --git a/tests/phpunit/CRMTraits/PCP/PCPTestTrait.php b/tests/phpunit/CRMTraits/PCP/PCPTestTrait.php
index f6d4113e9924a13a3fd2109f29ed895de72bdfbb..04db4f2a3b5c4675677403b3db1e7eb9d41c5163 100644
--- a/tests/phpunit/CRMTraits/PCP/PCPTestTrait.php
+++ b/tests/phpunit/CRMTraits/PCP/PCPTestTrait.php
@@ -73,4 +73,22 @@ trait CRMTraits_PCP_PCPTestTrait {
     return $params;
   }
 
+  /**
+   * Create a pcp block for testing.
+   *
+   * @param array $params
+   *
+   * @return int
+   */
+  protected function createPCPBlock(array $params):int {
+    $blockParams = $this->pcpBlockParams();
+    $pcpBlock = CRM_PCP_BAO_PCPBlock::create($blockParams);
+
+    $params = array_merge($this->pcpParams(), $params);
+    $params['pcp_block_id'] = $pcpBlock->id;
+
+    $pcp = CRM_PCP_BAO_PCP::create($params);
+    return (int) $pcp->id;
+  }
+
 }