-4
\$\begingroup\$

I have a class which uses the Azure SDK. The class has two constructors, shown in pseudo code below:

public StephensWorkerClass(){
   this.azureClient = await getNewAzureClient();
} //normally used

//just for testing
public StephensWorkerClass(IAzure azureClient){
   this.azureClient = azureClient; 
}

In normal usage, the empty constructor will be called and the constructor will do what needs to be done to make a new IAzure for us to use internally within the method.

To allow for unit testing, I made the second constructor which can recieved a Moq'd IAzure instance, and in my Unit tests, this works great.

My question though, is this an anti-pattern? If so, what's the way out from here? I was thinking I could make this method accept a nullable IAzure and if null, then call the method to new up a new IAzure client. Any tips?

\$\endgroup\$
  • 6
    \$\begingroup\$ Pseudo code is off topic on Code Review. Anyway, yes, the empty constructor is anti pattern. Inject the client instance from outside in both tests and "normal usage". \$\endgroup\$ – slepic Jul 14 at 14:26
1
\$\begingroup\$

I think you're on the right-track by using DI for unit-testing and you should just stick to it instead of only using it for testing.

Instead of having a parameterless constructor you could only have the constructor that receives an implementation (of IAzure) to which you can easily pass mock implementations for Unit Testing and add an extra layer of decoupling to your code base.

By sticking to DI for your class you can not only add mock implementations but you can also create "middleware" classes that implement the interface, do some extra work (like logging) and then forward the request to an actual implementation, for example.

| improve this answer | |
\$\endgroup\$
  • 5
    \$\begingroup\$ Please refuse to answer off-topic questions. \$\endgroup\$ – Heslacher Jul 14 at 14:51

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