Constructor dependency injection

The preceding code makes explicit hardcoded dependencies between classes. To work around this, CDI can be applied. This has been used in other languages, such as Java. In the following examples, Apex interfaces are utilized to express the dependencies between various units of code that you want to test in isolation.

It is not required to apply this to all method-to-method calling dependencies; only those that you want to apply unit testing to. Apex Enterprise Patterns focus mainly on the Services, Domain, Selector, and Unit Of Work classes.

By leveraging the ability to have multiple implementations of a given interface, we can vary which implementation gets executed. We can execute the real implementation of a method (this is provided by the preceding classes) or test only the mock behavior of it, typically defined in the test itself. Thus, depending on the type of test being written – an integration test or a unit test – you then pass the appropriate implementation of the Car class.

To support this type of injection, the following three things must be changed:

  1. Firstly, interfaces are created to reflect the methods on the Engine, Dashboard, and Display classes. The following code shows how these interfaces are defined:
public interface IEngine { 
    void start();       
    void stop(); 
    Boolean isRunning(); 
} 
public interface IDashboard { 
    void initialise(); 
    void updateRPMs(Integer rpms); 
    void off(); 
} 
public interface IDisplay { 
    void backlight(Boolean onOff); 
    void showMessage(
Integer positionX, Integer positionY, String message); String getMessageShowAt(
Integer positionX, Integer positionY); Boolean isVisible(); }
  1. Secondly, the real implementation of the classes must implement the interfaces, since the interfaces are based on their methods. This typically just requires stating that the class implements the interface:
public class Engine implements IEngine { 
 
public class Dashboard implements IDashboard { 
 
public class Display implements IDisplay {

  1. Finally, references to the interface types, and not the concrete classes, must be made throughout the code base. For example, the Car constructor now takes the interface types, as do the engine and dashboard member types, used to call the methods:
public class Car { 
     
    private IEngine engine; 
    private IDashboard dashboard; 
    private Boolean isRunning; 
     
    public Car(IEngine engine, IDashboard dashboard) { 
        this.dashboard = dashboard; 
        this.engine = engine; 
    } 
Notice that the integration test shown earlier in this chapter for the Car class still works without modification, since the real implementation it uses implements the interfaces.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.93.169