As the adage goes: You can solve every problem with another level of indirection, except for the problem of too many levels of indirection Reference
By introducing a wrapper / adapter your solution become a bit more loosely coupled.
Contract
So, first let's introduce the following interface:
public interface IBFactory
{
B Create();
}
Wrapper
Let's create the wrapper:
public class BWrapper: IBFactory
{
public B Create()
{
return SomeClass.StaticMethod();
}
}
Alternative
In case of C# 8 you can combine the previous two steps into one by relying on the default implementation in interface feature:
public interface IBFactory
{
public B Create()
{
return SomeClass.StaticMethod();
}
}
Relying on abstraction
Now let's modify the ClassWithAMethod
class to rely on the IBFactory
:
public class ClassWithAMethod
{
private readonly IBFactory _bFactory;
public ClassWithAMethod(IBFactory bFactory)
{
this._bFactory = bFactory;
}
public static void A(string email)
{
var b = this._bFactory.Create();
var c = b.GetUser(x => x.Email == email);
if (c != null)
{
throw new Exception();
}
}
}
You can register the BWrapper
as the default implementation for IBFactory
in your DI container. Or if you are not using DI nor C# 8 then you can specify a parameterless ctor where you rely on BWrapper
. Please bear in mind that this approach is not advised. It is more like a last resort.
public class ClassWithAMethod
{
private readonly IBFactory _bFactory;
public ClassWithAMethod()
{
this._bFactory = new BWrapper();
}
public ClassWithAMethod(IBFactory bFactory)
{
this._bFactory = bFactory;
}
...
}
Unit testing
Now you can mock that dependency as well.
var bFactoryMock = new Mock<IBFactory>();
bFactoryMock.Setup(factory => factory.Create()).Returns(...);
var SUT = new ClassWithAMethod(bFactoryMock.Object);