I am using JUNIT5, have been trying to fully coverage a piece of code that involves System.getenv(""); I writed a couple classes to replicate what I am experiencing right now and so you can use them to understand me also (minimal reproducible example):
First we have the service I need to get with full coverage (ServiceToTest.class) (it has a CustomContainer object which contains methods that it needs):
@Service public class ServiceToTest { private final CustomContainer customContainer; public ServiceToTest() { Object configuration = new Object(); String envWord = System.getenv("envword"); this.customContainer = new CustomContainer(configuration, envWord == null ? "default" : envWord); } public String getContainerName() { return customContainer.getContainerName(); } } CustomContainer.class:
public class CustomContainer { @Getter String containerName; Object configuration; public CustomContainer(Object configuration, String containerName) { this.configuration = configuration; this.containerName = containerName; } } I have tried using ReflectionTestUtils to set the envWord variable without success... I tried this https://stackoverflow.com/a/496849/12085680, also tried using @SystemStubsExtension https://stackoverflow.com/a/64892484/12085680, and finally I also tried using Spy like in this answer https://stackoverflow.com/a/31029944/12085680
But the problem is that this variable is inside the constructor so this only executes once and I think that it happens before any of this configs I tried before can apply, here is my test class:
@ExtendWith(MockitoExtension.class) class TestService { // I have to mock this becase in real project it has methods which I need mocked behavour private static CustomContainer mockCustomContainer = mock(CustomContainer.class); // The serviceToTest class in which I use ReflectionTestUtils to use the mock above // Here is where the constructor gets called and it happens BEFORE (debuged) the setup method // which is anotated with @BeforeAll private static ServiceToTest serviceToTest = new ServiceToTest(); @BeforeAll static void setup() { // set the field customContainer at serviceToTest class to mockCustomContainer ReflectionTestUtils.setField(serviceToTest, "customContainer", mockCustomContainer); } @Test void testGetContainerNameNotNull() { assertNull(serviceToTest.getContainerName()); } } I need to write a test in which serviceToTest.getContainerName is not null but the real purpose of this is to have coverage of this sentence envWord == null ? "default" : envWord so it would be a test that is capable of executing the constructor and mocking System.getenv() so that it returns not null...
Right now the coverage looks like this and I can not find a way to make it 100% Any ideas??
EDIT: So after following tgdavies suggestion, the code can be 100% covered, so this is the way:
Interface CustomContainerFactory:
public interface CustomContainerFactory { CustomContainer create(Object configuration, String name); } CustomContainerFactoryImpl:
@Service public class CustomContainerFactoryImpl implements CustomContainerFactory { @Override public CustomContainer create(Object configuration, String name) { return new CustomContainer(configuration, name); } } EnvironmentAccessor Interface:
public interface EnvironmentAccessor { String getEnv(String name); } EnvironmentAccessorImpl:
@Service public class EnvironmentAccessorImpl implements EnvironmentAccessor { @Override public String getEnv(String name) { return System.getenv(name); } } Class ServiceToTest after refactoring:
@Service public class ServiceToTest { private final CustomContainer customContainer; public ServiceToTest(EnvironmentAccessor environmentAccessor, CustomContainerFactory customContainerFactory) { Object configuration = new Object(); String envWord = environmentAccessor.getEnv("anything"); this.customContainer = customContainerFactory.create(configuration, envWord == null ? "default" : envWord); } public String getContainerName() { return customContainer.getContainerName(); } } Finally the test case after refactoring (here is were I think it can be improved maybe?):
@ExtendWith(MockitoExtension.class) class TestService { private static CustomContainer mockCustomContainer = mock(CustomContainer.class); private static CustomContainerFactory customContainerFactoryMock = mock(CustomContainerFactoryImpl.class); private static EnvironmentAccessor environmentAccessorMock = mock(EnvironmentAccessorImpl.class); private static ServiceToTest serviceToTest; @BeforeAll static void setup() { when(environmentAccessorMock.getEnv(anyString())).thenReturn("hi"); serviceToTest = new ServiceToTest(environmentAccessorMock, customContainerFactoryMock); ReflectionTestUtils.setField(serviceToTest, "customContainer", mockCustomContainer); when(serviceToTest.getContainerName()).thenReturn("hi"); } @Test void testGetContainerNameNotNull() { assertNotNull(serviceToTest.getContainerName()); } @Test void coverNullReturnFromGetEnv() { when(environmentAccessorMock.getEnv(anyString())).thenReturn(null); assertAll(() -> new ServiceToTest(environmentAccessorMock, customContainerFactoryMock)); } } Now the coverage is 100%:
EDIT 2:
We can improve the test class and get the same 100% coverage like so:
@ExtendWith(MockitoExtension.class) class TestService { private static CustomContainer mockCustomContainer = mock(CustomContainer.class); private static IContainerFactory customContainerFactoryMock = mock(ContainerFactoryImpl.class); private static IEnvironmentAccessor environmentAccessorMock = mock(EnvironmentAccessorImpl.class); private static ServiceToTest serviceToTest; @BeforeAll static void setup() { when(environmentAccessorMock.getEnv(anyString())).thenReturn("hi"); when(customContainerFactoryMock.create(any(), anyString())).thenReturn(mockCustomContainer); serviceToTest = new ServiceToTest(environmentAccessorMock, customContainerFactoryMock); } @Test void testGetContainerNameNotNull() { assertNotNull(serviceToTest.getContainerName()); } @Test void coverNullReturnFromGetEnv() { when(environmentAccessorMock.getEnv(anyString())).thenReturn(null); assertAll(() -> new ServiceToTest(environmentAccessorMock, customContainerFactoryMock)); } } 

when(serviceToTest.getContainerName()).thenReturn("hi");does nothing, becauseserviceToTestis not a mock. You want to mock that method onmockCustomContainer. You don't need to useReflectionTestUtils-- getcustomContainerFactoryMockto returnmockCustomContainer.