# Using Dry::Container with test mocks

**URL:** <https://discourse.dry-rb.org/t/using-dry-container-with-test-mocks/1354>\
**Category:** Support\
**Created:** [September 20, 2021, 10:11pm UTC](https://discourse.dry-rb.org/t/using-dry-container-with-test-mocks/1354 "2021-09-20T22:11:45Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![paul](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/paul/32/202_2.png) [@paul](https://discourse.dry-rb.org/u/paul)\
**Post date:** [September 20, 2021, 10:11pm UTC](https://discourse.dry-rb.org/t/using-dry-container-with-test-mocks/1354/1 "2021-09-20T22:11:45Z")

</div>

I have this pattern come up over and over again:

```ruby
class MyAdapter
  include Container[:my_client]

  def initialize(credentials, **deps)
    @credentials = credentials
    super(**deps)
  end
end

class DoSomething
  include Container[:my_adapter]

  def call(account)
    adapter = my_adapter.new(account.credentials)
    # ...
  end
end

module Container
  register(:my_client) { MyClient }
  register(:my_adapter) { MyAdapter }
end

RSpec.describe DoSomething
  let(:response) { { some: :json } }
  let(:client) { instance_double(MyClient, request: response) }
  let(:client_class) { class_double(MyClient, new: client) }

  let(:adapter_class) { class_double(MyAdapter, new: MyAdaper.new(my_client: client_class)) }
  # -- or --
  before { Container.stub(:my_client, client_class) }

  subject(:something) { DoSomething.new(my_adapter: adapter).call(account) }

  specify {
    expect(adapter_class).to have_received(:new).with(credentials) 
  }
  
  specify {
    expect(client).to have_received(:request).with(some_data) 
  }
end

```

I have classes that need to be initialized with some data besides their dependencies (in this case, some API credentials), and I have to set up those tedious class+instance mocks.

I noticed dry-rails’ autoloader uses dry-system to somehow auto-“new” things things it discovers to register (eg, loading “app/whatever/my\_command.rb” causes `AppContainer["my_command"]` to return an instance of `MyCommand` rather than the class itself. Is there a way to leverage that, but have control over the arguments that get passed to `initialize`?

Or is the expected pattern to just never have any objects that have to be initialized with non-dependencies? (Note this is difficult for things like adapters, which tend to have several methods that take independent args like the params to the API call as well as some data that’s always the same, like credentials).

I’ve also tried thing like defining `#new` as an instance method, so I can call it as many times as I want on an object, which is useful for tests, but feels gross otherwise.

```ruby
def new(credentials, **deps)
  self.class.new(credentials, **deps)
end

```

---

<div class="post-metadata">

**Author:** ![paul](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/paul/32/202_2.png) [@paul](https://discourse.dry-rb.org/u/paul)\
**Post date:** [September 20, 2021, 10:18pm UTC](https://discourse.dry-rb.org/t/using-dry-container-with-test-mocks/1354/2 "2021-09-20T22:18:31Z")

</div>

Another approach would be to separate the “dependencies” from the rest of the args, and make that a separate method/step. This feels decidedly non-ruby-like, though.

```ruby
class MyAdapter
  include Container[:my_client]

  def authenticate!(credentials)
    @credentials = credentials
  end

  def make_request(args)
    raise NotAuthenticated unless @credentials
    # do the work
  end
end

adapter = MyAdapter.new(dependencies)
adapter.authenticate!(account.credentials)
adapter.make_request(...)

```

---

<div class="post-metadata">

**Author:** ![wuarmin](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.dry-rb.org/wuarmin/32/641_2.png) [@wuarmin](https://discourse.dry-rb.org/u/wuarmin)\
**Post date:** [September 25, 2021, 10:58am UTC](https://discourse.dry-rb.org/t/using-dry-container-with-test-mocks/1354/3 "2021-09-25T10:58:03Z")

</div>

I worked around this issue with a custom bootable. Checkout: [Alba and Dependency Injections · Issue #105 · okuramasafumi/alba · GitHub](https://github.com/okuramasafumi/alba/issues/105#issuecomment-858654404)

You could create an adapter bootable and register your adapters class constants manually.
