Home > other >  Mocked class variable in a Spring Junit test showing Null
Mocked class variable in a Spring Junit test showing Null

Time:11-17

I have a Spring @Service and @Scope("prototype") class named StringCircularQueue, which has a constructor where a variable named queueName is getting initialized and a method addElement as below. To unit test this method inside the class, I am using JUnit Mockito to mock the RedisConnectionConfig which is being used in the addElement method.

When debugging the test, the redisConnectionConfig variable inside the addElement method shows null. But, if I comment out the constructor and run the same, the redisConnectionConfig variable shows a Non Null value.

Unable to figure out what is the issue when using the constructor. Any suggestions could be of great help.

@Service
@Scope("prototype")
public class StringCircularQueue {

    @Autowired
    private RedisConnectionConfig redisConnectionConfig;

    private String queueName;

    public StringCircularQueue(String queueName) {
        this.queueName = queueName;
    }
    
    public Boolean addElement(String element) {
      RedissonClient redisClient = redisConnectionConfig.getRedisClient();
      // Some other business logic
    }
} 
public class RedisCircularQueueTest {
    @InjectMocks
    RedisStringCircularQueue redisStringCircularQueue;
    
    @Mock
    private RedisConnectionConfig redisConnectionConfig;

    @Mock
    private RedissonClient redissonClient;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }
    
    @Test
    public void testAddElementToQueue() {
      Mockito.when(redisConnectionConfig.getRedisClient()).thenReturn(redissonClient);
      Boolean isAdded = redisStringCircularQueue.addElement("testString");
      Assert.assertEquals(true, isAdded);
   }
}

CodePudding user response:

Don't rely on field injection but on constructor injection in your StringCircularQueue as follows:

@Service
@Scope("prototype")
public class StringCircularQueue {

    private RedisConnectionConfig redisConnectionConfig;

    private String queueName;

    public StringCircularQueue(RedisConnectionConfig redisConnectionConfig, String queueName) {
        this.redisConnectionConfig = redisConnectionConfig;
        this.queueName = queueName;
    }
    
    public Boolean addElement(String element) {
      RedissonClient redisClient = redisConnectionConfig.getRedisClient();
      // Some other business logic
    }
} 

With this, your test will work.

The reason why it was null when you have the constructor is the following: Mockito will try to inject mocks only either by constructor injection, property injection or setter injection in this order. If the object is successfully created with the constructor, then Mockito won't try the other strategies, and that is why redisConnectionConfig is null because it has to be injected directly into the property itself. When you comment out the constructor, Mockito will only have the default no-args constructor of StringCircularQueue at its disposal. Since this does not inject anything, Mockito tries property injection, hence you get a non-null redisConnectionConfig this time. You can read more about this in the official documentation at https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/InjectMocks.html.

  • Related