This is the second day of my participation in the August More text Challenge. For details, see:August is more challenging

Initialize using a constructor

Constructor-style injection, which is heavily used in projects, has several benefits.

  • Use the final keyword to ensure that dependencies are immutable
  • Saves us checking it to make sure the dependency is not null
  • Ensure that the client (calling) code is returned in a fully initialized state
  • Circular dependencies are avoided
  • Improved code reusability

Especially in the aspect of cyclic dependency check, with the expansion of business, the original code structure is not reasonable, the code is not familiar enough and other factors may cause cyclic dependency. Before, after the project went online, the system exception was reported after the relevant function was clicked, and the reason was the circular dependency. After using the constructor injection mode, at the time of project startup, will be thrown BeanCurrentlyInCreationException: Requested bean is currently in creation: Is there an unresolvable circular reference.

This scenario can be used directly with @Mock and @InjectMocks

Business Code Example

@Service
public class EventService implements ModuleDtoQuery<EventDetailDTO> {

    private final AppService appService;
    private final EventRepo repo;

    @Autowired
    public EventService(AppService appService, EventRepo repo) {
        this.appService = appService;
        this.repo = repo; }}Copy the code

Unit test code sample

@RunWith(PowerMockRunner.class) public class EventServiceTest { @Mock AppService appService; @Mock EventRepo repo; @InjectMocks EventService eventService; @Test public void queryList() { ... }}Copy the code

List -> Map was added to constructor injection

Multiple implementations are injected through the interface, and then the interface is quickly obtained and the code is reduced through the List to Map.

Business Code Example

@Service
public class CatalogService {

    private final CatalogRepo catalogRepo;
    private final CatalogAssembler catalogAssembler;
    private final Map<Integer, CountByCatalog> countByCatalogMap;

    @Autowired
    public CatalogService(CatalogRepo catalogRepo, CatalogAssembler catalogAssembler, List
       
         countByCatalogList)
        {
        this.catalogRepo = catalogRepo;
        this.catalogAssembler = catalogAssembler;
        this.countByCatalogMap = countByCatalogList.stream() .collect(Collectors.toMap(CountByCatalog::getCatalogType, v -> v)); }}Copy the code

Unit test code sample

Using @Mock to simulate the set of interfaces, and then manually writing some implementation classes, we can get there.

@RunWith(PowerMockRunner.class)
@PrepareForTest({SpringContextUtils.class})
public class CatalogServiceTest {

    @Mock
    CatalogRepo catalogRepo;

    @Mock
    CatalogAssembler catalogAssembler;

    @Mock
    List<CountByCatalog> countByCatalog = Arrays.asList(new CountByCatalog() {
        @Override
        public int getCatalogType() {
            return 0;
        }
    });

    @InjectMocks
    CatalogService catalogService;
    
 }
Copy the code