Testing type of attribute of struct

(Sorry for all my posts :sweat_smile: I’m building a project with rom-rb and with a lot of dry-rb lib)

I want to unit test my struct. I want to know if an attribute is well typed.

For exemple I have a Company entity :

class Company < Dry::Struct
  constructor_type(:schema)

  attribute :email,         Types::Email.optional
end

The type ‘Types::Email’ is :

module Types
  include Dry::Types.module

  # Well formatted email (like xxxx@yyyy.zz)
  Email = Strict::String.constrained(format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i )

I want to do something like this (to ensure that Company’s attribute email is a Email type) :

expect(Company.email.class).to be(Types::Email)

I’m doing this, because I don’t want to test again the Types::Email, like I do here :

  describe 'Email' do
    it 'mus be well-formatted' do
      # valid cases
      expect(Types::Email['bill.gates@microsoft.ch']).to eq('bill.gates@microsoft.ch')
      expect(Types::Email['bill@microsoft.com']).to eq('bill@microsoft.com')

      # invalid cases
      expect{Types::Email['']}.to raise_error(Dry::Types::ConstraintError)
      expect{Types::Email['bill.gates']}.to raise_error(Dry::Types::ConstraintError)
      expect{Types::Email['bill.gatesATmicrosoft.ch']}.to raise_error(Dry::Types::ConstraintError)
      expect{Types::Email['bill.gates@microsoft']}.to raise_error(Dry::Types::ConstraintError)
    end
  end

I just want to ensure that email attribute of Company is the right type Types::Email

My goal here, is to avoid to test all email cases in 2 differents class (here in Types, and Company, and when the project will be increasing, in maybe Member, User,…)

If you want to test this, I’d write something that (1) ensures the struct can be initialised with valid attributes, and (2) the struct raises an error when initialised with an invalid email value. This second test wouldn’t need to be exhaustive, just something to signal that you’re doing type checking on the email.

2 Likes

Check out rspec-dry-struct.