I'm using mockito 1.9.5.
I have the following code:
public class ClassA {
public List<? extends MyInterface> getMyInterfaces() {
return null;
}
public static void testMock() {
List<MyInterface> interfaces = new ArrayList<>();
ClassA classAMock = mock(ClassA.class);
when(classAMock.getMyInterfaces()).thenReturn(interfaces);
}
I get a compilation error for the thenReturn(interfaces) saying:
"The method thenReturn(List<capture#1-of ? extends MyInterface>) in the type
OngoingStubbing<List<capture#1-of ? extends MyInterface>> is not applicable for the arguments
(List<MyInterface>)"
However, when I use the thenAnswer method of mockito, I don't get the error. Can anyone tell me what's going on? Why do I get the error when I use the thenReturn method?
Is there any other way to solve this problem when ClassA is provided by a 3rd party and cannot be modified?
EDIT : Starting from Mockito 1.10.x, generics types that are embedded in the class are now used by Mockito for deep stubs. ie.
public interface A<T extends Observer & Comparable<? super T>> {
List<? extends B> bList();
T observer();
}
B b = deep_stubbed.bList().iterator().next(); // returns a mock of B ; mockito remebers that A returns a List of B
Observer o = deep_stubbed.observer(); // mockito can find that T super type is Observer
Comparable<? super T> c = deep_stubbed.observer(); // or that T implements Comparable
Mockito tries its best to get type information that the compiler embeds, but when erasure applies, mockito cannot do anything but return a mock of Object.
Original : Well that's more of an issue with generics than with Mockito. For generics, you should read what Angelika Langer wrote on them. And for the current topic, i.e. wildcards, read this section.
But for short, what you could use is the other syntax of Mockito to help with your current situation :
doReturn(interfaces).when(classAMock).getMyInterfaces();
Or with the BDD aliases :
willReturn(interfaces).given(classAMock).getMyInterfaces();
Nevertheless, you could write wrappers that are more generic friendly. That will help future developers working with same 3rd party API.
As a side note: you shouldn't mocks type you don't own, it can lead to many errors and issues. Instead you should have some wrapper. DAO and repositories for example represent such idea, one will mock the DAO or repository interface, but not the JDBC / JPA / hibernate stuff. There are many blog posts about that:
http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html
http://blog.8thlight.com/eric-smith/2011/10/27/thats-not-yours.html
https://web.archive.org/web/20140923101818/http://freshbrewedcode.com/derekgreer/2012/04/01/tdd-best-practices-dont-mock-others/
...
Another solution (albeit less readable) is to qualify the static method call of when to bind the wildcard:
Mockito.<List<? extends MyInterface>>when(classAMock.getMyInterfaces()).thenReturn(interfaces);
Is there some tool to generate class hierarchy/dependency diagrams by inspecting C++ code in Linux?
I have this big collection of C++ files given to me and such a tool would be invaluable to help me
understand the source code. I am getting a little tangled up in understanding it.
Try doxygen. It may also be shipped with your distribution.
You may need GraphViz to generate the graphs. There is a simple example and output.
And this is a more complicated example from the legend file generated by doxygen:
Code (NOTE: if you only want to generate the graphs, the comments are not required.):
/*! Invisible class because of truncation */
class Invisible { };
/*! Truncated class, inheritance relation is hidden */
class Truncated : public Invisible { };
/* Class not documented with doxygen comments */
class Undocumented { };
/*! Class that is inherited using public inheritance */
class PublicBase : public Truncated { };
/*! A template class */
template<class T> class Templ { };
/*! Class that is inherited using protected inheritance */
class ProtectedBase { };
/*! Class that is inherited using private inheritance */
class PrivateBase { };
/*! Class that is used by the Inherited class */
class Used { };
/*! Super class that inherits a number of other classes */
class Inherited : public PublicBase,
protected ProtectedBase,
private PrivateBase,
public Undocumented,
public Templ<int>
{
private:
Used *m_usedClass;
};
Result:
You do not need to comment your code to generate these graphs. The first example has no comments at all. The second example has one class without doxygen style comment. Just set the appropriate parameter (at least EXTRACT_ALL = YES should be set. I cannot recall whether this is all that is needed).
There's a promising new tool called cpp-depenencies.
It can generate component dependency diagrams (like below) as well as class hierarchy diagrams (by passing an option to treat each source file as a component).
There's also cpp_dependency_graph, which is able to generate component/include dependency graphs in dot, d3.js or JSON formats.
Below is an example d3.js visualisation.
Disclaimer - I am the author of cpp_dependency_graph.
If you use Eclipse as IDE, you can use type hierarchy to see class hierarchy.
If you use kdevelop, you could install kdevcontrolflowgraphview plugin.
Source Trail is an easy-to-use tool in my experience with an intuitive GUI that helps you explore the relationship between a language element and others that are related to it. It worked very well for me on MacOS.
As of September 2021, it is no longer developed, but the repository remains available.
I have an interface in a unit testing framework: CDIMocker. I'm currently using an interceptor to allow mocking in a CDI container. It's an experiment - one of a couple of approaches to unit testing I'm considering. (The other main contender is to use constructor and method injection for all beans and unit test outside CDI - in which case this work becomes more a learning exercise in CDI Extensions).
I have two custom scopes - TestClassScoped and TestMethodScoped. My JUnit4 custom runner wraps the appropriate Class and Method blocks in statements that start and stop these scopes as needed. It also starts an instance of Weld-SE if needed. It knows if it's in CDI because the Extension remembers.
The mocker interface is the same wherever it us used. It would be nice to expose it in both scopes, so I could
// Sadly Static Injection currently doesn't work, but if it did
#Inject #TestClassScoped
private static CdiMocker s_classScopedMocker
#Inject #TestMethodScoped
private CdiMocker m_methodScopedMocker
There are other obvious ways. I currently have a factory method on a singleton outside CDI that can return either of these instances (ThreadLocal), or create a new short lived one. I have also had success creating two concrete classes and declaring different scopes on them.
I've tried using Producer Methods annotated as above, but no luck. Perhaps a simple mistake, perhaps a misunderstanding.
#Produces #TestClassScoped
public CdiMocker getClassScopedMockerForCdi()
{
return getTestClassContext().getMocker();
}
#Produces #TestMethodScoped
public CdiMocker getMethodScopedMockerForCdi()
{
return getTestMethodContext().getMocker();
}
I thought from some part of the CDI documentation it was possible to declare scopes on injection points as I have done, but I note that the Instance<> interface does not allow me to select() using scoped annotation so maybe that is wrong.
I could provide two qualifiers. Can an annotation be a Qualifier and a Scope at the same time?
Another idea would be to have my extension provide two Bean<CdiMocker>, both exposing the same class but in different scopes. They could also provide custom create() and destroy() because the CdiMocker instances are managed by my two custom Contexts. The impression I get of CDI is that a given Class can only live in one Scope, so would this be Wrong?
Any suggestions on what is best?
Thanks
- Richard
(I'd love to open source the result, but have done enough in work time I'd have to ask so not likely. The business argument would be public review. I use an Interceptor now with the disadvantage that it has to be left in place, but wonder if I could achieve something by intercepting the bean lifecycle in the extension. We can use Alternatives for things like the comms layer that talks to our legacy app server, but for some things a single unit test wants a custom mock and Alternatives are too global.)
I've created
#Qualifier
#Target({TYPE, METHOD, PARAMETER, FIELD})
#Retention(RUNTIME)
#Documented
public #interface Scoped
{
Class<? extends Annotation> value();
}
I currently have two Bean implementations. Relevant (unusual) parts are:
/**
* A Bean<> implementation for the CdiMocker beans
*/
class MockerBean implements Bean<CdiMocker>
{
private final class ScopedAnnotation extends AnnotationLiteral<Scoped> implements Scoped
{
private static final long serialVersionUID = 1L;
public Class<? extends Annotation> value() { return m_context.getScope(); }
}
private final CdiMockContextControl m_context;
public MockerBean(CdiMockContextControl context)
{
m_context = context;
}
The bean class is CdiMocker.class
#Override
public Class<?> getBeanClass()
{
return CdiMocker.class;
}
The Qualifiers include my ScopedAnnotation defined above. I've also included Default and Any. Maybe I need to remove these?
The scope is returned by my CdiMockContextControl interface.
#Override
public Class<? extends Annotation> getScope()
{
return m_context.getScope();
}
Type is my CdiMocker interface
#Override
public Set<Type> getTypes()
{
Set<Type> types = new HashSet<Type>();
types.add(CdiMocker.class);
types.add(Object.class);
return types;
}
Because the lifecycle is managed elsewhere I return the existing one.
#Override
public CdiMocker create(CreationalContext<CdiMocker> arg0)
{
return m_context.getMocker();
}
... and don't destroy it.
#Override
public void destroy(CdiMocker instance, CreationalContext<CdiMocker> ctx)
{
// It is managed by the Context, so I must not destroy it here.
ctx.release();
}
The solution is using Qualifiers, so I suppose it is now "Correct". I assume I can use lifecycle management in this way?
My test class (which my Runner instantiates using CDI) has
/**
* My CDI Extension makes a Mocking Context available in the Test Method Scope.
* This will be created before every test method, then destroyed afterwards.
*/
#Inject #Scoped(TestMethodScoped.class)
private CdiMocker m_testMethodMocker;
Richard
Our team has members who are just ramping up on unit testing and we're struggling with some terminology. I'd like to determine a name for a particular pattern. I'm hoping there's one that's already embraced by other developers, but if not, I'd like to come up with one that's descriptive and will make talking about test strategies easier.
This pattern is used quite a bit for testing abstract methods, but is also handy when an object creates a new object (for cases where DI doesn't work or isn't desired). The basic pattern is to use an inner class that extends the class under test to expose protected methods.
Consider the following code (which is pseudocode, based on Java, but should translate to most languages):
The class to test:
public class MyClass {
public void send() {
//do something
}
protected MailMessage createNewMailMessage() {
return new MailMessage();
}
}
The test:
public class MyClassTest {
private MyClass myClass = new TestableMyClass();
private MailMessage mockMessage = mock(MailMessage.class);
public void setup() {
((TestableMyClass)myClass).setMailMessage(mockMessage);
}
// Do some tests //
private class TestableMyClass extends MyClass {
private MailMessage mailMessage;
public void setMailMessage(MailMessage mailMessage) {
this.mailMessage = mailMessage;
}
protected MailMessage createNewMailMessage() {
return mailMessage;
}
}
}
So, what do you call this pattern? TestableMyClass a "Mock" object, but since it's not managed by a mocking framework, it seems like there should be another term to describe this pattern. Any suggestions or ideas?
I'd call it a stub. As you said, it's not a true "mock", since its behavior isn't being controlled by a mocking framework, but is a "true" object.
You don't need to use a mocking framework to call something a Mock/Stub object - your MyClassTest (which I'm assuming is supposed to extend MyClass) is just a Stub.
I don't think there's a particular name for the case where Mocks/Stubs are defined as inner classes of your test class - and in the particular example here, there's no reason for it to be an inner class - it could just be a package protected class (in the same file as MyClassTest or in its separate file..)
Mock contains test assertions.
Stub provides simple hard-coded values to make the test work.
Fake provides complex behavior/answers.
I usually add two underscores prefixing the inner class for testing so it doesn't show up in auto-complete, e.g. '__TestableMyClass'. Also if you are using Mockito you should be stubbing like so
MyClass myClass = mock(MyClass.class);
when(myClass.createNewMailMessage()).thenReturn(mockMessage);
How can i perform dependency injection without breaking encapsulation?
Using a Dependency Injection example from Wikipedia:
public Car {
public float getSpeed();
}
Note: Other methods and properties (e.g. PushBrake(), PushGas(),
SetWheelPosition() ) omitted for
clarity
This works well; you don't know how my object implements getSpeed - it is "encapsulated".
In reality my object implements getSpeed as:
public Car {
private m_speed;
public float getSpeed( return m_speed; );
}
And all is well. Someone constructs my Car object, mashes pedals, the horn, the steering wheel, and the car responds.
Now lets say i change an internal implementation detail of my car:
public Car {
private Engine m_engine;
private float m_currentGearRatio;
public float getSpeed( return m_engine.getRpm*m_currentGearRatio; );
}
All is well. The Car is following proper OO-principles, hiding details of how something is done. This frees the caller to solve his problems, rather than trying to understand how a car works. It also gives me the freedom to change my implementation as i see fit.
But dependency injection would force me to expose my class to an Engine object that i didn't create or initialize. Even worse is that I've now exposed that my Car even has an engine:
public Car {
public constructor(Engine engine);
public float getSpeed();
}
And now the outside word is aware that i use an Engine. I didn't always use an engine, i may want to not use an Engine in the future, but i can no longer change my internal implementation:
public Car {
private Gps m_gps;
public float getSpeed( return m_gps.CurrentVelocity.Speed; )
}
without breaking the caller:
public Car {
public constructor(Gps gps);
public float getSpeed();
}
But dependency injection opens a whole can of worms: by opening the whole can of worms. Dependency Injection requires that all my objects private implementation details be exposed. The consumer of my Car class now has to understand, and deal with, all of the previously hidden internal intricacies of my class:
public Car {
public constructor(
Gps gps,
Engine engine,
Transmission transmission,
Tire frontLeftTire, Tire frontRightTire, Tire rearLeftTire, Tire rearRightTire,
Seat driversSeat, Seat passengersSeat, Seat rearBenchSeat,
SeatbeltPretensioner seatBeltPretensioner,
Alternator alternator,
Distributor distributor,
Chime chime,
ECM computer,
TireMonitoringSystem tireMonitor
);
public float getSpeed();
}
How can i use the virtues of Dependency Injection to help unit testing, while not breaking the virtues of encapsulation to help usability?
See also
Must Dependency Injection come at the expense of Encapsulation? (Must, rather than how)
For the sake of fun, i can trim down the getSpeed example to just what is needed:
public Car {
public constructor(
Engine engine,
Transmission transmission,
Tire frontLeftTire, Tire frontRightTire
TireMonitoringSystem tireMonitor,
UnitConverter unitsConverter
);
public float getSpeed()
{
float tireRpm = m_engine.CurrentRpm *
m_transmission.GetGearRatio( m_transmission.CurrentGear);
float effectiveTireRadius =
(
(m_frontLeftTire.RimSize + m_frontLeftTire.TireHeight / 25.4)
+
(m_frontRightTire.RimSize + m_frontRightTire.TireHeight / 25.4)
) / 2.0;
//account for over/under inflated tires
effectiveTireRadius = effectiveTireRadius *
((m_tireMonitor.FrontLeftInflation + m_tireMontitor.FrontRightInflation) / 2.0);
//speed in inches/minute
float speed = tireRpm * effetiveTireRadius * 2 * Math.pi;
//convert to mph
return m_UnitConverter.InchesPerMinuteToMilesPerHour(speed);
}
}
Update: Perhaps some answer can follow the question's lead, and give sample code?
public Car {
public float getSpeed();
}
Another example is when my class depends on another object:
public Car {
private float m_speed;
}
In this case float is a class that is used to represent a floating-point value. From what i read, every dependant class should be injected - in case i want to mock the float class. This raises the spectre of having to inject every private member, since everything is fundamentally an object:
public Car {
public Constructor(
float speed,
float weight,
float wheelBase,
float width,
float length,
float height,
float headRoom,
float legRoom,
DateTime manufactureDate,
DateTime designDate,
DateTime carStarted,
DateTime runningTime,
Gps gps,
Engine engine,
Transmission transmission,
Tire frontLeftTire, Tire frontRightTire, Tire rearLeftTire, Tire rearRightTire,
Seat driversSeat, Seat passengersSeat, Seat rearBenchSeat,
SeatbeltPretensioner seatBeltPretensioner,
Alternator alternator,
Distributor distributor,
Chime chime,
ECM computer,
TireMonitoringSystem tireMonitor,
...
}
These really are implementation details that i don't want the customer to have to look at.
Many of the other answers hint at it, but I'm going to more explicitly say that yes, naive implementations of dependency injection can break encapsulation.
The key to avoiding this is that calling code should not directly instantiate the dependencies (if it doesn't care about them). This can be done in a number of ways.
The simplest is simply have a default constructor that does the injecting with default values. As long as calling code is only using the default constructor you can change the dependencies behind the scenes without affecting calling code.
This can start to get out of hand if your dependencies themselves have dependencies and so forth. At that point the Factory pattern could come into place (or you can use it from the get-go so that calling code is already using the factory). If you introduce the factory and don't want to break existing users of your code, you could always just call into the factory from your default constructor.
Beyond that there's using Inversion of Control. I haven't used IoC enough to speak too much about it, but there's plenty of questions here on it as well as articles online that explain it much better than I could.
If it should be truly encapsulated to where calling code cannot know about the dependencies then there's the option of either making the injecting (either the constructor with the dependency parameters or the setters) internal if the language supports it, or making them private and have your unit tests use something like Reflection if your language supports it. If you language supports neither then I suppose a possibility might be to have the class that calling code is instantiating a dummy class that just encapsulates the class the does the real work (I believe this is the Facade pattern, but I never remember the names correctly):
public Car {
private RealCar _car;
public constructor(){ _car = new RealCar(new Engine) };
public float getSpeed() { return _car.getSpeed(); }
}
If I understand your concerns correctly, you're trying to prevent any class that needs to instantiate a new Car object from having to inject all those dependencies manually.
I've used a couple patterns to do this. In languages with constructor chaining, I've specified a default constructor that injects the concrete types into another, dependency-injected constructor. I think this is a pretty standard manual DI technique.
Another approach I've used, which allows some looser coupling, is to create a factory object that will configure the DI'ed object with the appropriate dependencies. Then I inject this factory into any object that needs to "new" up some Cars at runtime; this allows you to inject completely faked Car implementations during your tests, too.
And there's always the setter-injection approach. The object would have reasonable defaults for its properties, which could be replaced with test-doubles as needed. I do prefer constructor-injection, though.
Edit to show a code example:
interface ICar { float getSpeed(); }
interface ICarFactory { ICar CreateCar(); }
class Car : ICar {
private Engine _engine;
private float _currentGearRatio;
public constructor(Engine engine, float gearRatio){
_engine = engine;
_currentGearRatio = gearRatio;
}
public float getSpeed() { return return _engine.getRpm*_currentGearRatio; }
}
class CarFactory : ICarFactory {
public ICar CreateCar() { ...inject real dependencies... }
}
And then consumer classes just interact with it through the interface, completely hiding any constructors.
class CarUser {
private ICarFactory _factory;
public constructor(ICarFactory factory) { ... }
void do_something_with_speed(){
ICar car = _factory.CreateCar();
float speed = car.getSpeed();
//...do something else...
}
}
I think you're breaking encapsulation with your Car constructor. Specifically you're dictating that an Engine must be injected to the Car instead of some type of interface used to determine your speed (IVelocity in the below example.)
With an interface, the Car is able to get it's current speed independent of what's determining that speed. For example:
public Interface IVelocity {
public float getSpeed();
}
public class Car {
private m_velocityObject;
public constructor(IVelocity velocityObject) {
m_velocityObject = velocityObject;
}
public float getSpeed() { return m_velocityObject.getSpeed(); }
}
public class Engine : IVelocity {
private float m_rpm;
private float m_currentGearRatio;
public float getSpeed( return m_rpm * m_currentGearRatio; );
}
public class GPS : IVelocity {
private float m_foo;
private float m_bar;
public float getSpeed( return m_foo * m_bar; );
}
An Engine or GPS can then have multiple interfaces based upon the type of work that it does. The interface is key to DI, without it DI does break encapsulation.
This is where I think you must use dependency injection containers that let you encapsulate the creation of your car, without letting your client callers need to know how to create it whatsoever. Here's how symfony solved this problem (even though it is not the same language, principles remain the same):
http://components.symfony-project.org/dependency-injection/documentation
there is a section on dependency injection containers.
To make it short and summarize it all quoted from the documentation page directly:
When using the container, we just ask
for a mailer object [This would be your car in your example], and we don't need
to know anything about how to create
it anymore; all the knowledge about
how to create an instance of the
mailer [car] is now embedded into the
container.
It the hope that it helps you
Factories and interfaces.
You've got a couple of questions here.
How can I have multiple implementations of the same operations?
How can I hide construction details of an object from the consumer of an object?
So, what you need is to hide the real code behind an ICar interface, create a separate EnginelessCar if you ever need one, and use an ICarFactory interface and a CarFactory class to hide the construction details from the consumer of the car.
This will likely end up looking a lot like a dependency injection framework, but you do not have to use one.
As per my answer in the other question, whether or not this breaks encapsulation depends entirely on how you define encapsulation. There are two common definitions of encapsulation that I've seen:
All operations on a logical entity are exposed as class members, and a consumer of the class doesn't need to use anything else.
A class has a single responsibility, and the code to manage that responsibility is contained within the class. That is, when coding the class, you can effectively isolate it from its environment and reduce the scope of the code you're working with.
(Code like the first definition can exist in a codebase that works with the second condition - it just tends to be limited to facades, and those facades tend to have minimal or no logic).
I haven't used Delphi in a long time. The way DI works in Spring, your setters and constructor aren't part of the interface. So you can have multiple implementations of an interface, one might use constructor-based injection and another might use setter-based injection, your code that uses the interface doesn't care. What's injected is in the application-context xml, and that is the only place that your dependencies are exposed.
EDIT:
If you use a framework or not you're doing the same thing, you have a factory that wires together your objects. So your objects expose these details in the constructor or in setters, but your application code (outside of the factory, and not counting tests) never uses them. Either way you choose to get your object graph from the factory rather than instantiate stuff on the fly, and you choose to not do things like use setters in the code that are there to be injected into. It is a mind-shift from the "nail-everything-down" philosophy I see from some people's code.
I don't think a car is a particularly good example of the real world usefulness of dependency injection.
I think in the case of your last code example, the purpose of the Car class is not clear. Is is a class that holds data/state? Is it a service to calculate things like speed? Or is it a mix, allowing you to construct its state and then call services on it to make calculations based on that state?
The way I see it, the Car class itself would likely be a stateful object, whose purpose is to hold the details of its composition, and the service to calculate speed (which could be injected, if desired) would be a separate class (with a method like "getSpeed(ICar car)"). Many developers who use DI tend to separate stateful and service objects--although there are cases where an object will have both state and service, the majority tend to be separated. In addition, the vast majority of DI usage tends to be on the service side.
The next question would be: how should the car class be composed? Is the intent that every specific car is just an instance of a Car class, or is there a separate class for each make and model that inherit from CarBase or ICar? If it's the former, then there must be some means of setting/injecting these values into the car--there is no way around this, even if you'd never heard of dependency inversion. If it's the latter, then these values are simply part of the car, and I would see no reason to ever want to make them settable/injectable. It comes down to whether things like Engine and Tires are specific to the implementation (hard dependencies) or if they are composable (loosely coupled dependencies).
I understand the car is just an example, but in the real world you are going to be the one who knows whether inverting dependencies on your classes violates encapsulation. If it does, the question you should be asking is "why?" and not "how?" (which is what you are doing, of course).
You should break your code into two phases:
Construction of the object graph for a particular lifetime via factory or DI solution
Running these objects (which will involve input and output)
At the car factory, they need to know how to build a car. They know what sort of engine it has, how the horn is wired in etc. This is phase 1 above. The car factory can build different cars.
When you are driving the car, you can drive anything that meets the car interface you expect. e.g. pedals, steering wheel, horn. When you're driving you don't know the internal details when you press the brake. You can, however, see the result (change in speed).
Encapsulation is maintained as no one driving a car needs to know how it was built. Therefore, you can use the same driver with many different cars. When the drive needs a car, they should be given one. If they build their own when they realise they need one, then encapsulation will be broken.
Now, for something completely different...
You want the virtues of dependency injection without breaking encapsulation. A dependency injection framework will do that for you, but there is also a "poor man's dependency injection" available to you through some creative use of virtual constructors, meta class registration and selective inclusion of units in your projects.
It does have a serious limitation though: you can only have a single specific Engine class in each project. There is no picking an choosing engine's, though come to think of it, you could probably mess with the value of the meta class variable to achieve just that. But I am getting ahead of myself.
Another limitation is a single line of inheritance: just a trunk, no branches. At least with regard to the units included in a single project.
You seem to be using Delphi and therefore the method below will work as it is something that we have been using since D5 in projects that need a single instance of class TBaseX, but different projects need different descendants of that base class and we want to be able to swap classes by simply chucking out one unit and adding another. The solution isn't restricted to Delphi though. It will work with any language that supports virtual constructors and meta classes.
So what do you need?
Well, every class that you want to be able to swap depending on units included per project, needs to have a variable somewhere in which you can store the class type to instantiate:
var
_EngineClass: TClass;
Every class that implements an Engine should register itself in the _EngineClass variable using a method that prevents ancestors from taking the place of a descendant (so you can avoid dependence on unit initialisation order):
procedure RegisterMetaClass(var aMetaClassVar: TClass; const aMetaClassToRegister: TClass);
begin
if Assigned(aMetaClassVar) and aMetaClassVar.InheritsFrom(aMetaClassToRegister) then
Exit;
aMetaClassVar := aMetaClassToRegister;
end;
Registration of the classes can be done in a common base class:
TBaseEngine
protected
class procedure RegisterClass;
class procedure TBaseEngine.RegisterClass;
begin
RegisterMetaClass(_EngineClass, Self);
end;
Each descendant registers itself by calling the registration method in its unit's initialization section:
type
TConcreteEngine = class(TBaseEngine)
...
end;
initialization
TConcreteEngine.RegisterClass;
Now all you need is something to instantiate the "descendent most" registered class instead of a hard coded specific class.
TBaseEngine
public
class function CreateRegisteredClass: TBaseEngine;
class function TBaseEngine.CreateRegisteredClass: TBaseEngine;
begin
Result := _EngineClass.Create;
end;
Of course you should now always use this class function to instantiate engines and not the normal constructor.
If you do that, your code will now always instantiate the "most descendant" engine class present in your project. And you can switch between classes by including and not including the specific units. For example you can ensure your test projects use the mock classes by making the mock class an ancestor of the actual class and not including the actual class in the test project; or by making the mock class a descendant of the actual class and not including the mock in your normal code; or - even simpler - by including either the mock or the actual class in your projects.
Mock and actual classes have a parameter-less constructor in this implementation example. Doesn't need to be the case, but you will need to use a specific meta class (instead of TClass) and some casting in the call to the RegisterMetaClass procedure because of the var parameter.
type
TBaseEngine = class; // forward
TEngineClass = class of TBaseEngine;
var
_EngineClass: TEngineClass
type
TBaseEngine = class
protected
class procedure RegisterClass;
public
class function CreateRegisteredClass(...): TBaseEngine;
constructor Create(...); virtual;
TConcreteEngine = class(TBaseEngine)
...
end;
TMockEngine = class(TBaseEngine)
...
end;
class procedure TBaseEngine.RegisterClass;
begin
RegisterMetaClass({var}TClass(_EngineClass), Self);
end;
class function TBaseEngine.CreateRegisteredClass(...): TBaseEngine;
begin
Result := _EngineClass.Create(...);
end;
constructor TBaseEngine.Create(...);
begin
// use parameters in creating an instance.
end;
Have fun!