1

This question is a follow-up question to Clean Architecture use case testing.

Suppose the production code injects Use Case Interactor into the Input Boundary - that happens somewhere in the main component1. But now I want to test the Input Boundary/Output Boundary of the use case. I can only think of two ways to do this:

  1. Recreate the dependency injection setup at the beginning of the test - this forces the test to depend on Use Case Interactor.
  2. Depend on the main component for DI - this seems risky because the main component is volatile.

Is there a clean way to handle this situation?

1 Clean Architecture Chapter 26, Robert C Martin

8
  • Do you want to unit test InputBoundary in isolation, or do you want to create an integration test for InputBoundary and UseCaseInteractor?
    – Doc Brown
    Jul 29 at 16:01
  • @The latter, I want to test that boundary of the use case.
    – Brady Dean
    Jul 29 at 16:03
  • You want to test InputBoundary which depends on UseCaseInteractor - so to test InputBoundary you must pass instance of UseCaseInteractor. It is ok for test to depend on input parameters (UseCaseInteractor is an input parameter of InputBoundary which passed via constructor).
    – Fabio
    Jul 30 at 5:31
  • 1
    @BradyDean, you said I want to test the Input Boundary/Output Boundary of the use case - that mean you have an implementation of these interfaces, which takes UseCaseInteractor as a constructor argument (I assume)
    – Fabio
    Jul 30 at 21:10
  • 1
    @BradyDean, Should the test manually instantiate UseCaseInteractor - did you try that? Did this approach cause any issues? You need to start with something
    – Fabio
    Jul 31 at 1:02
0

How can I manage dependency injection in test code?

The same way you manage it in production code.

Suppose the production code injects Use Case Interactor into the Input Boundary

Then production code is confused because you don't inject classes into interfaces.

But now I want to test the Input Boundary/Output Boundary of the use case

Stop that. Test behavior not structure. The boundaries do not hold behavior. They define the mini language that can be used to communicate across the boundary. Tests should use that same mini language to test what's across the boundary.

I think it would be best to test UseCaseInteractor directly, rather than throught the boundaries. @Brady Dean

Using UseCaseInteractor through the boundary is the direct way. Anything else is sneaking past the abstraction you're meant to use. Tests that sneak in the back door only prove that the back door works.

Is there a clean way to handle this situation?

Focus on the behavior you expect when you use the unit under test in the way it's meant to be used. Don't worry about isolation unless that's needed to make the unit's behavior deterministic and fast. Don't go sneaking around abstractions. And stop treating behaviorless structure code as something that needs to be tested.

1
  • It's apparent I didn't ask the question clearly enough. But now I want to test the Input Boundary/Output Boundary of the use case should have been But now I want to test the use case through the IO Boundaries (which you did well describing as the "direct way"). As for the dependency injection stuff - I had in mind something like ASP.NET Core's IOC container where you ask for an IInputBoundary and are given a UseCaseInteractor object. I suppose that for the purpose of testing, these objects should just be created by hand.
    – Brady Dean
    Aug 29 at 19:31
0

The input boundary is a simple abstraction to prevent the controller from knowing about the specific use case interactor. It doesn’t do anything, it simply invokes the interactor.

If your language supports generics, you can makes this a generic class. In your test, create a fake interactor and use that to test the generics.

Personally I use the Mediatr library (C#). All interactors implement an IRequestHandler interface and input data implements IRequest. Inject Mediatr into the controller, create a new request and call mediator.Send(request);. It doesn’t get much cleaner than that and because you can rely on a library you don’t even have to write and test the glue code yourself!

2
  • I think my concern is with how coupled the tests should be to the internals of the use case. I think the test ought to be independent of the specific use case implementation, but DI forces a decision to be made before the test can execute.
    – Brady Dean
    Jul 29 at 18:42
  • specificInteractor.Handle(request) - clean one line without dependencies on third party libraries(Mediatr) ;)
    – Fabio
    Jul 29 at 20:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.