Closed srnagar closed 4 years ago
@mssfang Could this be closed? I've seen mocks being used in the AppConfiguration tests from PRs I've reviewed.
Thanks for checking this up. Close this issue now.
I honestly I am not convinced of the approach of marking Azure SDK classes with final
nor providing an interfaces for these classes. Sure, having a wrapper with fake dependency works many times, not only with Azure SDK, but it should be done with every third party sdk. However, there are instances, that fake implementation (not mocked) by either implementing an interface or overriding the client class to provide these to your system code. Sure, I can mock something like this here, but honestly I don't find it sustainable to do mocking like this, I rather implement a client interface and provide a fake implementation, e.g for AWS stub, you can see there was no any mocking being done there, only fake implementation.
Hello @srnagar.
Let's say that I created an interface that provides azure storage blob services to my entire application.
Once this interface is created, an implementation that uses azure blob services directly to provide storage service.
Now, how unit test case for this specific implementation would be written ? As you said, most of the azure java sdk classes are final, how can I unit test this implementation alone without mocking final classes or fakes as there is no interface available.
Please pardon me if my understanding is not upto the mark. I am still learning ways of properly writing software.
I'm unable to easily mockito my azure classes still.
With 12.14.0-beta.1 it seems to be still public final class BlobServiceClient
... :|
Mocks in unit tests
Unit tests are aimed at testing small isolated components of code that can be predictably executed any number of times to yield the same outcome.
Mocks provide a convenient mechanism to circumvent interaction with methods that are outside the scope of your unit tests. This will let you focus on testing the code that is in scope for your unit tests and not worry about external classes/libraries/dependencies.
Having said that, code should be testable without using any of the mocking libraries like Mockito, JMockit etc. "Fakes rather than Mocks". A fake object is simply a replacement for the real object. While a real object may have actual business logic, a fake object may simply return canned responses.
Instead, you could inject a fake dependency
However, mocking libraries help in writing your tests faster. In the previous example, a fake implementation had to be created to write unit tests. Mocks can make this faster by letting you mock the behavior of real object without writing lot of code for faking dependencies.
Good candidates for using a mock:
Don't mock
Static methods - Libraries like PowerMock allow mocking static methods but it comes at a cost. It meddles with the default classloader and can lead to inconsistent behavior in tests and production runtime. Also, some of these libraries interfere with test coverage instrumentation and result in incorrect test coverage reports.
Solution: If you need to mock a static method, first evaluate if there's a way to refactor your code and eliminate the need for static method. If that's not possible, then consider isolating the static method access by wrapping it in a method that can be easily mocked.
Consider doing
Mocking Final classes
If you are using Mockito, it requires additional configuration to be able to mock
final
classes as described in Mockito 2 documentation.Note that most of (if not all) the client classes provided in Azure SDK are
final
. These clients use the network to communicate with Azure services.As a consumer of Azure SDK client libraries, your application is taking a dependency on 3rd party library that making network calls. In such scenarios, it's a good idea for your application to abstract out the dependency and hide it behind your own interface. This will contain the scope of dependency just within the implementation of the interface and your application is only using the interface you have defined. This allows your application to switch between different implementations of the interface without having to make changes to your application. The added benefit is that now your unit tests can either use a fake implementation as shown in the example at the top of this page or use a mock without requiring special configuration to enable mocking of
final
classes.