Using a double with Instance attribute modifier

Hello,

Is it possible for a double to bypass the Instance check on a dry-struct attribute? For instance:

require 'dry-struct'
require 'spec_helper'

class B
end

class A < ::Dry::Struct
  include Dry::Types.module
  constructor_type(:schema)
  attribute :b, Instance(B).optional
end


describe 'something' do
  it 'test' do
    b = instance_double('B')
    expect(
      A.new(b: b)
    ).to be
  end
end

I’ve tried to mock several methods from both B and b and was not able to make this test pass.

instance_double returns something that is not an instance of B, so the check in Instance(B) will fail whatever you do. Maybe you can find another way to design and test your behavior without the need of doubles, probably allowing your dependencies to be injected so that you can use lighter ones in your test suite:

# Without injection

class A
  def foo
    # You won't be able to change B in your test suite as it is a hard coded dependency.
    B.new.do_something
  end
end

# With injection

class A
  attr_reader :b
  
  def initialize(b:)
    @b = b
  end

  def foo
    # Now, in your test suite you can do `A.new(b: TestB.new)` and you don't need to create a double for B
    b.do_something
  end
end

dry-auto_inject can help you to avoid boilerplate code.

Storing something beyond plain data structures in dry-struct seems like an anti-pattern to me.

1 Like