diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3edf20364fd462c8186041f49923fbd46d67c796..c69abfac0e71e9befb15ed47a7a1810d29e11cc9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -45,6 +45,7 @@ release.
 - Added backplane options for SunIllumination and SurfaceObliqueDetectorResolution to phocube [#5467](https://github.com/DOI-USGS/ISIS3/issues/5467)
 
 ### Changed
+- Explode has been refactored to be callable; old Makefile test has been removed and replaced by a gtest. Issue: [#5557](https://github.com/USGS-Astrogeology/ISIS3/issues/5557)
 - Isisminer has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5516](https://github.com/USGS-Astrogeology/ISIS3/issues/5516)
 - Algebra has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5594](https://github.com/USGS-Astrogeology/ISIS3/issues/5594)
 - Photrim has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5581](https://github.com/USGS-Astrogeology/ISIS3/issues/5581)
diff --git a/isis/src/base/apps/explode/explode.cpp b/isis/src/base/apps/explode/explode.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fdf39bb7278961af6abc764debafde5d023d0321
--- /dev/null
+++ b/isis/src/base/apps/explode/explode.cpp
@@ -0,0 +1,97 @@
+/** This is free and unencumbered software released into the public domain.
+
+The authors of ISIS do not claim copyright on the contents of this file.
+For more details about the LICENSE terms and the AUTHORS, you will
+find files of those names at the top level of this repository. **/
+
+/* SPDX-License-Identifier: CC0-1.0 */
+
+#include "explode.h"
+
+#include "ProcessByLine.h"
+#include "IException.h"
+#include "FileName.h"
+
+namespace Isis {
+  
+  // Line processing routine
+  void CopyBand(Buffer &in, Buffer &out);
+
+  /**
+   * Extracts each band of the input cube into a separate one band cube file.
+   * Given the output base name of "base", each output cube will be named
+   * e.g. base.band#.cub. The appropiate BandBin group will be created.
+   *
+   * @param ui User Interface with application parameters
+   */
+  void explode(UserInterface &ui) {
+
+    // open input cube
+    Cube icube;
+    icube.open(ui.GetCubeName("FROM"));
+
+    explode(&icube, ui);
+  }
+
+
+  /**
+   * Extracts each band of the input cube into a separate one band cube file.
+   * Given the output base name of "base", each output cube will be named
+   * e.g. base.band#.cub. The appropiate BandBin group will be created.
+   *
+   * @param ui User Interface with application parameters
+   * @param icube Input cube
+   */
+  void explode(Cube *icube, UserInterface &ui) {
+    
+    Process p;
+    p.SetInputCube(icube);
+    int samps = icube->sampleCount();
+    int lines = icube->lineCount();
+    int bands = icube->bandCount();
+    QString infile = icube->fileName();
+
+    // We get the output filename so we can add attributes and extensions
+    QString outbase = ui.GetCubeName("TO");
+    CubeAttributeOutput &outatt = ui.GetOutputAttribute("TO");
+
+    // Loop and extract each band
+    for(int band = 1; band <= bands; band++) {
+      int pband = icube->physicalBand(band);
+      QString sband(toString(pband));
+
+      ProcessByLine p2;
+      Progress *prog = p2.Progress();
+      prog->SetText("Exploding band " + sband);
+
+      CubeAttributeInput inatt("+" + sband);
+      p2.SetInputCube(infile, inatt);
+
+      QString outfile = outbase + ".band";
+      if(pband / 1000 == 0) {
+        outfile += "0";
+        if(pband / 100 == 0) {
+          outfile += "0";
+          if(pband / 10 == 0) {
+            outfile += "0";
+          }
+        }
+      }
+      outfile += sband + ".cub";
+      p2.SetOutputCube(outfile, outatt, samps, lines, 1);
+
+      p2.StartProcess(CopyBand);
+      p2.EndProcess();
+    }
+
+    // Cleanup
+    p.EndProcess();
+  }
+
+  // Line processing routine
+  void CopyBand(Buffer &in, Buffer &out) {
+    for(int i = 0; i < in.size(); i++) {
+      out[i] = in[i];
+    }
+  }
+}
diff --git a/isis/src/base/apps/explode/explode.h b/isis/src/base/apps/explode/explode.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc945f280ee328235e8c8eadc9a348097ab048ca
--- /dev/null
+++ b/isis/src/base/apps/explode/explode.h
@@ -0,0 +1,19 @@
+/** This is free and unencumbered software released into the public domain.
+
+The authors of ISIS do not claim copyright on the contents of this file.
+For more details about the LICENSE terms and the AUTHORS, you will
+find files of those names at the top level of this repository. **/
+
+/* SPDX-License-Identifier: CC0-1.0 */
+
+#ifndef explode_h
+#define explode_h
+
+#include "UserInterface.h"
+
+namespace Isis{
+  extern void explode(UserInterface &ui);
+  extern void explode(Cube *icube, UserInterface &ui);
+}
+
+#endif
diff --git a/isis/src/base/apps/explode/explode.xml b/isis/src/base/apps/explode/explode.xml
index adaef0f30753dee59da431d797f1f3a9db5c1242..c9c7e6e8ca08402d3890db0f4c6bc7c89b5bd9bd 100644
--- a/isis/src/base/apps/explode/explode.xml
+++ b/isis/src/base/apps/explode/explode.xml
@@ -35,6 +35,9 @@
     <change name="Steven Lambright" date="2008-05-12">
       Removed references to CubeInfo 
     </change>
+    <change name="Ken Edmundson" date="2024-08-15">
+      Converted to callable app and converted Makefile test to gtest. 
+    </change>
   </history>
 
   <groups>
diff --git a/isis/src/base/apps/explode/main.cpp b/isis/src/base/apps/explode/main.cpp
index 7a75d1ccba1e7ff6238626b1bdd1ce6c4e4c02c9..f2ff2442ee75eea706fe5a9c2f3df1f4b77d0a04 100644
--- a/isis/src/base/apps/explode/main.cpp
+++ b/isis/src/base/apps/explode/main.cpp
@@ -1,63 +1,20 @@
-#include "Isis.h"
-#include "ProcessByLine.h"
-#include "IException.h"
-#include "FileName.h"
-
-using namespace std;
-using namespace Isis;
-
-void CopyBand(Buffer &in, Buffer &out);
+/** This is free and unencumbered software released into the public domain.
 
-void IsisMain() {
-  // Get the cube to explode
-  Process p;
-  Cube *icube = p.SetInputCube("FROM");
-  int samps = icube->sampleCount();
-  int lines = icube->lineCount();
-  int bands = icube->bandCount();
-  QString infile = icube->fileName();
-
-  // We the output filename so we can add attributes and extensions
-  UserInterface &ui = Application::GetUserInterface();
-  QString outbase = ui.GetCubeName("TO");
-  CubeAttributeOutput &outatt = ui.GetOutputAttribute("TO");
+The authors of ISIS do not claim copyright on the contents of this file.
+For more details about the LICENSE terms and the AUTHORS, you will
+find files of those names at the top level of this repository. **/
 
-  // Loop and extract each band
-  for(int band = 1; band <= bands; band++) {
-    int pband = icube->physicalBand(band);
-    QString sband(toString(pband));
+/* SPDX-License-Identifier: CC0-1.0 */
 
-    ProcessByLine p2;
-    Progress *prog = p2.Progress();
-    prog->SetText("Exploding band " + sband);
-
-    CubeAttributeInput inatt("+" + sband);
-    p2.SetInputCube(infile, inatt);
+#include "Isis.h"
 
-    QString outfile = outbase + ".band";
-    if(pband / 1000 == 0) {
-      outfile += "0";
-      if(pband / 100 == 0) {
-        outfile += "0";
-        if(pband / 10 == 0) {
-          outfile += "0";
-        }
-      }
-    }
-    outfile += sband + ".cub";
-    p2.SetOutputCube(outfile, outatt, samps, lines, 1);
+#include "explode.h"
 
-    p2.StartProcess(CopyBand);
-    p2.EndProcess();
-  }
+#include "Application.h"
 
-  // Cleanup
-  p.EndProcess();
-}
+using namespace Isis;
 
-// Line processing routine
-void CopyBand(Buffer &in, Buffer &out) {
-  for(int i = 0; i < in.size(); i++) {
-    out[i] = in[i];
-  }
+void IsisMain() {
+  UserInterface &ui = Application::GetUserInterface();
+  explode(ui);
 }
diff --git a/isis/src/base/apps/explode/tsts/Makefile b/isis/src/base/apps/explode/tsts/Makefile
deleted file mode 100644
index 46d84c74c297304e943452a44e06b111f179a92b..0000000000000000000000000000000000000000
--- a/isis/src/base/apps/explode/tsts/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-BLANKS = "%-6s"    
-LENGTH = "%-40s"
-
-include $(ISISROOT)/make/isismake.tststree
diff --git a/isis/src/base/apps/explode/tsts/case01/Makefile b/isis/src/base/apps/explode/tsts/case01/Makefile
deleted file mode 100644
index e58baa1d0db1a9ecb50cffdc798811c611d52577..0000000000000000000000000000000000000000
--- a/isis/src/base/apps/explode/tsts/case01/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-APPNAME = explode
-
-include $(ISISROOT)/make/isismake.tsts
-
-commands:
-	$(APPNAME) from=$(INPUT)/isisTruth.cub \
-	  to= $(OUTPUT)/explTruth1 > /dev/null;
diff --git a/isis/tests/FunctionalTestsExplode.cpp b/isis/tests/FunctionalTestsExplode.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b639d8a25c7e34f399b4fe44f3296b82c82dca40
--- /dev/null
+++ b/isis/tests/FunctionalTestsExplode.cpp
@@ -0,0 +1,80 @@
+#include "explode.h"
+
+#include <QFileInfo> 
+#include <QString>
+
+#include "CameraFixtures.h"
+#include "Cube.h"
+#include "Histogram.h"
+
+#include "gtest/gtest.h"
+
+using namespace Isis;
+
+static QString APP_XML = FileName("$ISISROOT/bin/xml/explode.xml").expanded();
+
+/**
+   * ExplodeDefault Test
+   * 
+   * ExplodeDefault test given a single 5x5 input cube with 2 bands.
+   *
+   * The output cube is verified by checking the histogram statistics
+   * for each band.
+   * 
+   * INPUT: testCube from DefaultCube fixture resized to 5x5x1
+   * 
+   * OUTPUT: 1) explodeOut.band0001.cub
+   *         2) explodeOut.band0002.cub
+   */
+TEST_F(DefaultCube, FunctionalTestExplodeDefault) {
+
+  // reduce test cube size and create two bands
+  resizeCube(5, 5, 2);
+
+  // close and reopen test cube to ensure dn buffer is available
+  testCube->reopen("r");
+
+  // run explode  
+  QVector<QString> args = {"to=" + tempDir.path() + "/explodeOut"};
+  UserInterface ui(APP_XML, args);
+
+  try {
+    explode(testCube, ui);
+  }
+  catch(IException &e) {
+    FAIL() << e.toString().toStdString().c_str() << std::endl;
+  }
+
+  // validate band 1 output cube
+  Cube outCube1(tempDir.path() + "/explodeOut.band0001.cub");
+
+  ASSERT_EQ(outCube1.sampleCount(), 5);
+  ASSERT_EQ(outCube1.lineCount(), 5);
+  ASSERT_EQ(outCube1.bandCount(), 1);
+
+  std::unique_ptr<Histogram> inCubeBand1Hist (testCube->histogram(1));
+  std::unique_ptr<Histogram> outCube1Hist (outCube1.histogram(1));
+
+  EXPECT_NEAR(outCube1Hist->Average(), inCubeBand1Hist->Average(), .000001);
+  EXPECT_NEAR(outCube1Hist->Sum(), inCubeBand1Hist->Sum(), .000001);
+  EXPECT_EQ(outCube1Hist->ValidPixels(), inCubeBand1Hist->ValidPixels());
+  EXPECT_EQ(outCube1Hist->TotalPixels(), inCubeBand1Hist->TotalPixels());
+  EXPECT_NEAR(outCube1Hist->StandardDeviation(), inCubeBand1Hist->StandardDeviation(), .000001);
+
+  // validate band 2 output cube
+  Cube outCube2(tempDir.path() + "/explodeOut.band0002.cub");
+
+  ASSERT_EQ(outCube2.sampleCount(), 5);
+  ASSERT_EQ(outCube2.lineCount(), 5);
+  ASSERT_EQ(outCube2.bandCount(), 1);
+
+  std::unique_ptr<Histogram> inCubeBand2Hist (testCube->histogram(2));
+  std::unique_ptr<Histogram> outCube2Hist (outCube2.histogram(1));
+
+  EXPECT_NEAR(outCube2Hist->Average(), inCubeBand2Hist->Average(), .000001);
+  EXPECT_NEAR(outCube2Hist->Sum(), inCubeBand2Hist->Sum(), .000001);
+  EXPECT_EQ(outCube2Hist->ValidPixels(), inCubeBand2Hist->ValidPixels());
+  EXPECT_EQ(outCube2Hist->TotalPixels(), inCubeBand2Hist->TotalPixels());
+  EXPECT_NEAR(outCube2Hist->StandardDeviation(), inCubeBand2Hist->StandardDeviation(), .000001);
+}
+