1

I have a class that would highly benefit from Unit tests, but few methods that call remote web server must be replaced by something delivering mock results. The probable solutions I see are:

  • Test the derived class that overrides problematic methods (no test-related code in production, just methods must be non-private and non final).
  • Extract problematic methods into separate component.

The second case requires to add this component somehow during both tests and production runs, and may have at least the following solutions:

  • Have protected field that can be directly assigned during the setup of the test, replacing the component there. Somewhat breaks OOP concepts.
  • Have the setter to set the component. It is still not the best API as this component cannot be suddenly replaced after the main object becomes active with its functions. It would be a method with the limited time window to call.
  • Have the constructor that takes either web-interacting implementation or mock. This makes the API somewhat strange (always construct and pass the same object).
  • Have the second constructor for testing only that takes a mock, production constructor calls this(..) with the production instance pre-constructed.
  • Have something like naming service that resolves the component (looks like lots of work to create and maintain it, if just for testing support, singleton pattern).
  • Use dependency injection framework (if the project is smaller, also looks like lots of overhead).

Which of these proposed solutions are "theoretically correct"? Or maybe some other solutions are more correct?

  • 1
    Dependency-injection via constructor parameters is definitely the way to go. The overhead of using a DI framework on a small projects pays off when you move on to larger projects already knowing how to use it. – Timothy Truckle Jun 6 '17 at 9:17
  • My answer regarding a similar topic might be a help to you. – Andy Jun 6 '17 at 11:03
5

Separate the remote calls into a separate object, and supply it through the constructor. This is the cleanest solution, since you would want this separation anyway (due to separation of concerns), and it mean you can introduce a dependency injection framework if you feel it would provide benefit, but you don't have to, you can also provide the dependency "manually" if you find it simpler.

The other solutions you propose generally have the drawback that you add testing-specific code directly to the domain logic.

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.