Back to Repositories

Testing Secure JSON Serialization in Devise

This test suite evaluates the serialization behavior of Devise user models, focusing on JSON serialization security and key handling. It verifies proper handling of sensitive data during serialization and ensures appropriate key filtering mechanisms are in place.

Test Coverage Overview

The test suite provides comprehensive coverage of JSON serialization security features:
  • Key filtering for sensitive data
  • Customizable exclusion patterns
  • Forced exclusion handling
  • Object inspection safety
  • Frozen options support

Implementation Analysis

The testing approach employs ActiveSupport::TestCase with focused unit tests for JSON serialization. It utilizes helper methods for consistent assertion patterns and implements systematic verification of key presence and absence in serialized output.

Technical Details

Testing infrastructure includes:
  • ActiveSupport::TestCase framework
  • Custom assertion helpers (assert_key, assert_no_key)
  • JSON parsing utilities
  • User factory setup
  • Frozen options handling

Best Practices Demonstrated

The test suite exemplifies several testing best practices:
  • Isolated test cases with clear purpose
  • Helper method abstraction for common operations
  • Comprehensive edge case coverage
  • Security-focused validation
  • Clean setup and teardown patterns

heartcombo/devise

test/models/serializable_test.rb

            
# frozen_string_literal: true

require 'test_helper'

class SerializableTest < ActiveSupport::TestCase
  setup do
    @user = create_user
  end

  test 'should not include unsafe keys on JSON' do
    keys = from_json().keys.select{ |key| !key.include?("id") }
    assert_equal %w(created_at email facebook_token updated_at username), keys.sort
  end

  test 'should not include unsafe keys on JSON even if a new except is provided' do
    assert_no_key "email", from_json(except: :email)
    assert_no_key "confirmation_token", from_json(except: :email)
  end

  test 'should include unsafe keys on JSON if a force_except is provided' do
    assert_no_key "email", from_json(force_except: :email)
    assert_key "confirmation_token", from_json(force_except: :email)
  end

  test 'should not include unsafe keys in inspect' do
    assert_match(/email/, @user.inspect)
    assert_no_match(/confirmation_token/, @user.inspect)
  end

  test 'should accept frozen options' do
    assert_key "username", @user.as_json({ only: :username, except: [:email].freeze }.freeze)["user"]
  end

  def assert_key(key, subject)
    assert subject.key?(key), "Expected #{subject.inspect} to have key #{key.inspect}"
  end

  def assert_no_key(key, subject)
    assert_not subject.key?(key), "Expected #{subject.inspect} to not have key #{key.inspect}"
  end

  def from_json(options = nil)
    ActiveSupport::JSON.decode(@user.to_json(options))["user"]
  end
end