The term explain
SUT (System Under Test) The system under test
DOC (来 源 component) Third-party dependent Components

Introduction & Understanding

TestDouble is a TestDouble. In most cases, our system relies not only on the system itself, but also on external services such as HTTP and RPC services provided by other systems. Database services such as Redis cache service or mysql from the system itself. In the microservice scenario, the business divides A system into multiple systems according to the business domain, and the interaction between the systems is not just A->B, but A->B -> C ->D. For the developer who writes unit tests, it is impossible to build A complete call link when I need to write test cases of system A. In test engineering, “test surrogates” are often used to solve the test complexity caused by external dependencies.

When conducting unit tests, the main purpose of using Test Double is to reduce the dependence of the tested object and make the Test more simple. It only needs to focus on some Test scenarios of the system under Test. In addition, the Test Double, in some ways, allows the Test case to run shorter and more stable tests (instead of real external dependencies).

There is a fundamental difference between the Test Double and the actual object delivered, so overuse of the Test Double is not recommended in the actual testing process, as it may cause a disconnect between the Test scenario and the actual scenario.

Test surrogate type

Test surrogates mainly include the following types:

  1. Dummy Object
  2. Test Stub
  3. Test Spy
  4. Mock Object
  5. Fake Object

Dummy Object

Virtual objects, which have no effect on testing per se, actually exist only as populating class roles with similar parameters.

Test Stub

The test pins are used to accept indirect inputs from within the SUT and return specific values to the SUT. The Test Stub is, understandably, a Stub inside the SUT that returns specific content to the SUT as required. The Test Stub’s interaction is entirely inside the SUT, so it does not return content to the Test case, nor does it validate input inside the SUT.

A Test Stub is an object that completely replaces the dependent components of the system under Test. This object interacts with the system under Test according to the output we designed. It can be understood as a stake in the system under Test. This peg neither interacts with the test case (code) nor validates within the system under test. The Test Stub is often used to respond to requests from the system under Test and then return specific values. This value will then have an effect on the system under test, and we will verify this effect in the test case.

The Test Stub can be implemented in either of the following ways:

  1. Hard-coded Test Stub – a Test Stub that will return a fixed response
  2. A Configurable Test Stub, which sends a different response based on the Test requirements

The Test Stub comes in handy when we encounter the following scenario

  • Dependent components cannot be used, affecting test results
  • Dependent components run too slowly, affecting test speed
  • Become a Responder when it is necessary to inject specific data into the system under test, thereby affecting the system under test
  • Become a Saboteur, when you need to inject invalid data into the system under test, so as to have an abnormal effect on the system under test. How does the system under test handle the error situation

Test Spy

The Test Spy, like a Spy, is embedded in the SUT and is responsible for transferring its indirect outputs to the outside world. It is characterized by returning indirect internal output to the Test case for verification. The Test Spy is only responsible for obtaining internal intelligence and sending it out, but not verifying the accuracy of the intelligence.

A Test Spy is a proxy for a dependent component of the system under Test and captures and saves the output of the object under Test to the dependent system for validation in the Test code. Test Spy is mainly used to record and verify the output of the object under Test to dependent systems.

The Test Spy takes the output of the Object to the dependent system and verifies it in the Test code. This way, if the output of the SUT does not meet expectations, the Test Spy will not fail the Test in the first place, as the Mock Object does. Instead, the Test Spy can add more judgment information to the Test code. Make validation and test results more controllable and visible.

Mock Object

The Mock Object is similar to the Test Spy in that it is embedded in the SUT and has indirect outputs from the SUT. The Mock Object is also responsible for verifying intelligence (indirect Outputs), and headquarters (external test cases) trusts the Mock Object’s verification results.

Mocks are more like a given behavior, with expected inputs producing expected outputs from Mock objects.

An important feature of a Mock Object is that it validates behavior or output that cannot be directly observed on the system under test. Unobservable system behavior or output can be data being inserted into a database, data being written to a file, or calls to other components. The Mock Object database, for example, accepts data from the system under test and validates it. Once validated, the data is processed (insert or update) and the test code verifies that the insert was successful.

Fake Object

Fake Object does not care about indirect inputs or indirect outputs inside SUT. It is simply a substitute for an actual Object and has almost the same functions as the actual Object to ensure that the SUT works properly. Real objects are overly dependent on the external environment, and Fake Objects can reduce this dependency. This is the main difference between Fake and Test Stub.

In short, this is a simpler way to implement the functionality of dependent components. A typical example is to use H2 instead of Mysql testing.

Reference documentation

  • bliki: TestDouble
  • Mocks Aren’t Stubs
  • Test Double