I think a factory method would serve you well here.
Mark your base test fixture as abstract and define a protected abstract method with the same signature as the service constructors. Then, call that method in your base fixture's setup logic.
You will have to implement the abstract method for each derived test class, but I think it's a reasonable compromise.
Note that I also removed the interface from the test class. Based on the sample code you provided, it's entirely redundant with the now-abstract base class. Of course, it might be useful for some reason not apparent from your example--if so, you can keep it.
public class BaseServiceUnitTest<TEntity> where TEntity : BaseEntity
{
private IBaseService<TEntity> _service;
public BaseServiceUnitTest(Constructor ctor)
{
_service = Create(/* your mocked dependencies here */);
}
protected abstract IBaseServce<TEntity> Create(Dependency1 d1, Dependency2 d2);
//...implemented methods from IBaseServiceUnitTest
}
public class CustomEntityServiceUnitTest : BaseServiceUnitTest<CustomEntity>
{
// "arg1, arg2"
protected override IBaseService<CustomEntity> Create(Dependency1 d1, Dependency2 d2) =>
new BaseService<CustomerEntity>(d1, d2);
}
Addendum
If you really want to make things automagic, you could try the answer to this question. It'll work, but you'll sacrifice "F12-ability" (the ability to find and navigate through references using Visual Studio's shortcuts) and compile-time verification of your constructors and their arguments. Personally, I'd probably use the factory method.
Addendum #2
For completeness, it's also worth noting that if your service-under-test had no constructor arguments, you might also be able to use the new
constraint. Based on your comments, it doesn't sound like it will work in this case, but it might be useful another time.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…