Introducing unit testing

As we will discover throughout this chapter, unit testing helps to address the preceding challenges. When used in combination with integration tests, the resulting test suite creates a much stronger and more efficient set of Apex tests for your application.

Learning about and writing unit tests can often seem difficult because it requires you to learn other concepts, some of which determine how you write your application code. Things such as separation of concerns (SOC), dependency injection, mocking, and test-driven development are concepts you will come across when googling about unit tests. We will be looking into these throughout this chapter. Of course, you are already, by now, quite familiar with SOC and how it is applied to Apex Enterprise Patterns. As a reminder, in Chapter 6, Application Domain Layer, we briefly described unit testing as having the following characteristics:

  • The term "unit" refers to a small portion of application code that has inputs and outputs (including exceptions) you want to focus on ensuring quality for as a developer. In object-orientated programming languages such as Apex, this could be an interface, or public methods on a class, or just a specific method.
  • The unit "test code" for such a method focuses on invoking the method or interface in as many different combinations of inputs and expected outputs (including exceptions) as possible.
  • It's good practice to write test code that uses as many inputs as possible and not just those you imagine the current callers might use. This ensures the unit of code being tested is robust enough for future scenarios. This can be quite important for Domain-class code testing, as this class of code protects the integrity of customers' data.

The biggest difference between unit and integration testing is evident through this definition. Unit tests can cover methods on potentially any class in your code base, not just the outer controller classes or service classes. Furthermore, the goal is to test the execution and behavior of only the code in the chosen method and nothing else.

The hard part can be preventing the execution of other methods that the method being unit tested calls. This is done by substituting parts of the real production code (within the test context only) for stubbed code, or what is referred to as mocked code, which emulates the behavior of those methods. Then, the method you're unit testing can still execute. Ideally, the method should be unaware of this substitution, or injection as it's known.

For example, a unit test for an Apex Controller method should test the behavior of that method only, such as interaction with the view state or the handling of UI requests and responses with the service layer calls. What the service layer method does is not of interest. Developers should not have to consider any requirements of dependent methods like this (for example, database setup) in the unit test code. Likewise, when testing the Apex service layer logic, its use of the Unit Of Work, Selector, and Domain classes are not of interest or concern. However, these dependencies need to be resolved. The next section discusses how to inject dependencies.

The following diagram shows a series of unit tests focusing on Apex classes using mock alternatives of the dependent class to avoid having to be concerned with their needs:

In contrast, the following diagram shows a series of unit tests focusing on Lightning Web Components and uses mock alternatives for the dependent components and services:

A mock version of a dependent class, component, or service should emulate the expectations of the calling code (the code the unit test is focusing on) by returning a value or throwing an exception, for example. Configuring mocking is a key setup aspect of unit testing you need to master. It can allow you to write some very sophisticated and varied tests. We will go into more detail on mocking later in the chapter.

The more developers invest in unit tests, the less likely integration tests and your end users are to find defects. Keep in mind, however, that proving that methods work in isolation does not prove your application works as designed. Integration tests are still a critical tool in testing your application.

..................Content has been hidden....................

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