Home > Software design >  How to write a test for a service in which beans self-register
How to write a test for a service in which beans self-register

Time:04-07

Problem with correct class setting for tests.

I have the following service structure

My service:

Interface

public interface ColumnsFromTableService {
    List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName);
    DataProviderSourceType  myDataProviderSourceType();
    @Autowired
    default void regMe(ColumnsFromTableFacade columnsFromTableFacade){
        columnsFromTableFacade.register(myDataProviderSourceType(),this);
    }
}

Impl

@Service
@RequiredArgsConstructor
public class OracleColumnsFromTableServiceImpl implements ColumnsFromTableService {
    private final DataProviderInsideDao dataProviderInsideDao;

    @Override
    public List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName) {
        return dataProviderInsideDao.getColumnsByTableNameFromOracle(dataProvider, tableName);
    }

    @Override
    public DataProviderSourceType myDataProviderSourceType() {
        return DataProviderSourceType.ORACLE;
    }
}

My facade:

Interface

public interface ColumnsFromTableFacade {
    List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName);
    void register(DataProviderSourceType dataProviderSourceType, ColumnsFromTableService columnsDataProviderService);
}

Impl

@Service
public class ColumnsFromTableFacadeImpl implements ColumnsFromTableFacade {
    private final Map<DataProviderSourceType, ColumnsFromTableService> implementationMap = new HashMap<>();

    @Override
    public List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName) {
       
        ColumnsFromTableService columnsFromTableService = implementationMap.get(dataProvider.getSourceType());
        return columnsFromTableService.getTableColumnsFromSource(dataProvider,tableName);
     
    }

    @Override
    public void register(DataProviderSourceType dataProviderSourceType, ColumnsFromTableService columnsDataProviderService) {
        implementationMap.put(dataProviderSourceType, columnsDataProviderService);
    }
}

For use, I inject the facade in the place I need.

Everything works in the application. When creating ColumnsFromTableService beans, Spring Boot sees the @Autowired annotation in the interface and and registers the service in the facade. But when testing this facade, I can't set it up correctly.

My test:

@ExtendWith(MockitoExtension.class)
public class EasyServiceTest {

    @InjectMocks
    TablesFromSourceFacadeImpl tablesFromSourceFacade;

    @Test
    void test(){       
        tablesFromSourceFacade.getAllTablesFromSource(new DataProvider());
    }
}

When running the test, the facade is successfully instantiated. But the collection with implementations is empty.

enter image description here

I am using Junit jupiter - 5.7.1 Spring boot - 2.4.3

CodePudding user response:

you have not provided class source code for TablesFromSourceFacadeImpl. So, its difficult to say what beans that class is expecting. but, in general, check this article to understand how @InjectMocks works: https://www.baeldung.com/mockito-annotations

all the beans that you class TablesFromSourceFacadeImpl requires must be declared and mock instances using @Mock annotation. The effect is, all the @Autowired beans are wired with Mock instance that you have reference to in you test file and thus are available for stubbing.

CodePudding user response:

I decided to be rough


@ExtendWith(MockitoExtension.class)
public class EasyServiceTest {
    
    TablesFromSourceFacadeImpl tablesFromSourceFacade;
    @InjectMocks
    OracleTablesFromSourceServiceImpl oracleTablesFromSourceService;
    @InjectMocks
    OracleColumnsFromTableServiceImpl oracleColumnsFromTableService;

    @BeforeEach
    void setUp() {
        tablesFromSourceFacade = new TablesFromSourceFacadeImpl();
        tablesFromSourceFacade.register(postgresTablesFromSourceService.myDataProviderSourceType(),
                                        postgresTablesFromSourceService);
        tablesFromSourceFacade.register(oracleTablesFromSourceService.myDataProviderSourceType(),
                                        oracleTablesFromSourceService);
    }
    @Test
    void test(){       
        tablesFromSourceFacade.getAllTablesFromSource(new DataProvider());
    }
}

  • Related