diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 564a2d6889b548d884ff285a7944d85abad0f6a1..796b56026b9dc67432fd656cc327e7bf2f4e81ac 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,8 @@
 variables:
   CI_DEFAULT_BRANCH: legacy-main
   CI_PROJECT_NAME: nshmp-haz-legacy
+  JACOCO_HTML_DIR: ${REPORTS_DIR}/jacoco/test/html
+  JUNIT_FILES: build/test-results/test*/TEST-*.xml
   PRODUCTION_BRANCH: legacy-production
   UPSTREAM_PATH: ghsc/nshmp/nshmp-haz
 
@@ -12,6 +14,11 @@ workflow:
 
 stages:
   - build
+  - test
+
+default:
+  tags:
+    - nshmp
 
 ####
 # Environment Templates
@@ -53,6 +60,17 @@ stages:
   variables:
     ENVIRONMENT: production
 
+
+####
+# Java Templates
+####
+
+##
+# General Java setup
+##
+.java:
+  image: ${DEVOPS_REGISTRY}usgs/amazoncorretto:8
+
 ####
 # Docker Templates
 ####
@@ -125,7 +143,6 @@ stages:
   stage: build
   tags:
     - build
-  variables:
 
 ####
 # Stage: build
@@ -140,3 +157,29 @@ Build Image:
       FROM_IMAGE=${DEVOPS_REGISTRY}usgs/amazoncorretto:8
     DOCKERFILE: Dockerfile
     IMAGE_TAG: ${ENVIRONMENT}-${CI_COMMIT_SHORT_SHA}
+
+Build Project:
+  extends:
+    - .java
+  script:
+    - ./gradlew assemble
+  stage: build
+
+####
+# Stage: test
+####
+
+Unit Tests:
+  artifacts:
+    paths:
+      - ${JACOCO_HTML_DIR}
+    reports:
+      junit: ${JUNIT_FILES}
+  coverage: '/Total.*?([0-9]{1,3})%/'
+  extends:
+    - .java
+  needs: []
+  script:
+    - ./gradlew check
+    - cat ${JACOCO_HTML_DIR}/index.html
+  stage: test