Menuka Ishan
Menuka Ishan

Reputation: 5504

Testing with Junit 5 failed in Spring boot

I have a Service class like below.

public class DependantServiceImpl implements DependantService {

private DependantRepository dependantRepository;
private EmployeeRepository employeeRepository;

private final CompanyEntity companyEntity;

private final String DEPENDANT_ROLE = "dependant";

@Autowired
public DependantServiceImpl(
        CompanyEntity companyEntity, DependantRepository dependantRepository,
        EmployeeRepository employeeRepository) {

    this.companyEntity = companyEntity;
    this.dependantRepository = dependantRepository;
    this.employeeRepository = employeeRepository;
}

I use factory method like below to get Service layer.

@Service
public class DependantServiceFactoryImpl implements DependantServiceFactory {

    private final DependantRepository dependantRepository;
    private final EmployeeRepository employeeRepository;
    private final CompanyRepository companyRepository;

    @Autowired
    public DependantServiceFactoryImpl(
            CompanyRepository companyRepository, DependantRepository dependantRepository,
            EmployeeRepository employeeRepository) {

        this.dependantRepository = dependantRepository;
        this.employeeRepository = employeeRepository;
        this.companyRepository = companyRepository;
    }

    @Override
    public DependantService dependantServiceForCompany(String companyId) {

        return companyRepository.findById(companyId)
                .map(companyEntity -> new DependantServiceImpl(
                        companyEntity, dependantRepository, employeeRepository))
                .orElseThrow(() ->
                        new IllegalArgumentException(String.format("Invalid Compnay Id [{%s}]", companyId)));

    }
}

I want to write unit tests for Service class (DependantServiceImpl) but for that, I have to get the service class through DependantServiceFactoryImpl CRUD Repository (Because all repositories extended from Hibernate CRUD repository.) injecting to the constructor. But problem is that I can't inject the repositories to DependantServiceFactoryImpl. I tried many ways like below.

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = DependantServiceFactoryImpl.class)
public class DependantServiceImplTest {

    @MockBean
    DependantRepository dependantRepository;
    @MockBean
    EmployeeRepository employeeRepository;
    @MockBean
    CompanyRepository companyRepository;

    @Autowired
    DependantServiceFactory dependantServiceFactory;

    @Test
    @DisplayName("Get dependant succesfully test")
    void getDependentsTest() {

        String companyId = "1";
        String employeeId = "9a76bb33-772c-4c41-b2eb-eb40500d7026";


        List<DependantEntity> dependantEntityList = dependantServiceFactory
                .dependantServiceForCompany(companyId)
                .getDependents(employeeId);

        assertTrue(dependantEntityList.size() > 0);
    }

But I get below error (for full error check the link https://gist.github.com/Menuka5/de6cd71b6e39e0895cf9be4e7ba34b3d)

java.lang.IllegalArgumentException: Invalid Compnay Id [{1}]

Can someone point out a way to create working Unit tests, please. Thanks in Advance. :)

Upvotes: 0

Views: 458

Answers (1)

JB Nizet
JB Nizet

Reputation: 691635

There are 3 big mistakes here:

  1. It's supposed to be a unit test of DependantServiceImpl, so no, you don't need to call your factory to get a service instance. You also don't need SpringExtension, MockBean and Autowired. You just need to call the constructor of DependantServiceImpl passing a real entity, and mock instances (created with Mockito) of the repositories.
  2. You annotated the DependantServiceImpl constructor with Autowired, but that makes no sense, since DependantServiceImpl is not a Spring bean, is not created by Spring, and can't possibly be injected with CompanyEntity since that's not a Spring bean.
  3. If you want your test to stay as is and work, you need to mock the companyRepository.findById() method and make it return a non-empty Optional. Otherwise, of course, the value it returns is an empty Optional, so the orElseThrow() callback is called, and you get that exception.

Upvotes: 1

Related Questions