I have one parametrized Junit test in my class. If I initialize all objects used in this test in @Before method they are not accessible in this parametrized Junit test and it throws NUllPointer Exception, due to which I have to initialize all theses objects again in parametrized Junit test. Why is this behavior ?

This is my parametrized Junit test where I have initialize all objects again and even I need to mock them also again.

    @ParameterizedTest
    @CsvSource({"1,5550,true","1,0,false","0,5550,false"})
    public void itemsAvailableValidatorTest(int kioskId, int siteNbr,Boolean expected) throws Exception {

        ItemAvailableRequest request = new ItemAvailableRequest();
        ItemAvailableRequestValidator itemAvailableRequestValidator = new ItemAvailableRequestValidator();


        context = Mockito.mock(ConstraintValidatorContext.class);
        builder = Mockito.mock(ConstraintValidatorContext.ConstraintViolationBuilder.class);

        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()))
                .thenReturn(builder);
        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()).addConstraintViolation())
                .thenReturn(context);



        // set ndc and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = new ArrayList<>();
        ndcs.add("1234");
        famIds.add(1234);

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);
        request.setKioskId(kioskId);
        request.setQty(1);
        request.setSiteNbr(siteNbr);
        request.setRxFillId(null);        // call the custom validator method and verify the response
        assertEquals(expected, itemAvailableRequestValidator.isValid(request, context));
    }

If I initialize the Following objects of this test in @Before method or at class level this test fails and throughs NullPointer Exception

ItemAvailableRequest request = new ItemAvailableRequest();
        ItemAvailableRequestValidator itemAvailableRequestValidator = new ItemAvailableRequestValidator();


        context = Mockito.mock(ConstraintValidatorContext.class);
        builder = Mockito.mock(ConstraintValidatorContext.ConstraintViolationBuilder.class);

        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()))
                .thenReturn(builder);
        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()).addConstraintViolation())
                .thenReturn(context);

Why the objects initialized in Before method or at class level are not accessible in @parametrized JunitTest ? and why they need to be specifically initialized inside @paramterized Junit test curly brackets.

Here is the code for whole class

package com.walmart.rxkioskinventory.validator;

import com.walmart.rxkioskinventory.model.request.ItemAvailableRequest;
import com.walmart.rxkioskinventory.model.validator.ItemAvailableRequestValidator;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;

import javax.validation.ConstraintValidatorContext;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class ItemAvailableRequestValidatorTest {


    @InjectMocks
    ItemAvailableRequestValidator itemAvailableRequestValidator;

    private ItemAvailableRequest request;
    private ConstraintValidatorContext context;
    private ConstraintValidatorContext.ConstraintViolationBuilder builder;


    /*
   good request initializer
    */
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        // mock the context
        context = Mockito.mock(ConstraintValidatorContext.class);

        context = Mockito.mock(ConstraintValidatorContext.class);
        builder = Mockito.mock(ConstraintValidatorContext.ConstraintViolationBuilder.class);


        // context.buildConstraintViolationWithTemplate returns
        // ConstraintValidatorContext.ConstraintViolationBuilder
        // so we mock that too as you will be calling one of it's methods
        builder = Mockito.mock(ConstraintValidatorContext.ConstraintViolationBuilder.class);

        // when the context.buildConstraintViolationWithTemplate is called,
        // the mock should return the builder.
        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()))
                .thenReturn(builder);
        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()).addConstraintViolation())
                .thenReturn(context);
        request = new ItemAvailableRequest();

        // set ndc and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = new ArrayList<>();
        ndcs.add("1234");
        famIds.add(1234);

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);
        // error for binding the request
        Errors errors = new BeanPropertyBindingResult(request, "request");

    }

    /*
    test to verify the valid request with all valid request params
     */
    @Test
    public void itemsAvailableValidatorSuccessTest() throws Exception {
        ItemAvailableRequest request = new ItemAvailableRequest();

        // set ndc and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = new ArrayList<>();
        ndcs.add("1234");
        famIds.add(1234);

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);
        request.setKioskId(1);
        request.setQty(1);
        request.setSiteNbr(5550);
        request.setRxFillId(1);

        // call the custom validator method and verify the response
        assertEquals(true, itemAvailableRequestValidator.isValid(request, context));
    }

    /**
     *Test to verify response when request is null
     */
    @Test
    public void itemsAvailableValidatorNullRequestTest()  {
        ItemAvailableRequest request = null;

        // call the custom validator method and verify the response
        assertEquals(false, itemAvailableRequestValidator.isValid(request, context));
    }

    /**
     *Test to verify response when quantity is invalid.
     */
    @Test
    public void itemsAvailableValidatorInvalidQuantityTest()  {
        ItemAvailableRequest request = new ItemAvailableRequest();

        // set ndc and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = null;
        ndcs.add("1234");

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);
        request.setKioskId(1);
        request.setQty(0.5);
        request.setSiteNbr(5550);
        request.setRxFillId(null);
        // call the custom validator method and verify the response
        assertEquals(false, itemAvailableRequestValidator.isValid(request, context));
    }


    /**
     *  Test to verify response when SiteNbr is invalid
     * @param kioskId it depicts kiosk id
     * @param siteNbr it depicts site nbr
     * @throws Exception it throws exception
     */
    @ParameterizedTest
    @CsvSource({"1,5550,true","1,0,false","0,5550,false"})
    public void itemsAvailableValidatorTest(int kioskId, int siteNbr,Boolean expected) throws Exception {

        ItemAvailableRequest request = new ItemAvailableRequest();
        ItemAvailableRequestValidator itemAvailableRequestValidator = new ItemAvailableRequestValidator();


        context = Mockito.mock(ConstraintValidatorContext.class);
        builder = Mockito.mock(ConstraintValidatorContext.ConstraintViolationBuilder.class);

        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()))
                .thenReturn(builder);
        Mockito.when(context.buildConstraintViolationWithTemplate(Mockito.anyString()).addConstraintViolation())
                .thenReturn(context);



        // set ndc and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = new ArrayList<>();
        ndcs.add("1234");
        famIds.add(1234);

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);
        request.setKioskId(kioskId);
        request.setQty(1);
        request.setSiteNbr(siteNbr);
        request.setRxFillId(null);        // call the custom validator method and verify the response
        assertEquals(expected, itemAvailableRequestValidator.isValid(request, context));
    }
    /*
test to verify that if  rxFillId is 0 then request is not valid
 */
    @Test
    public void itemsAvailableValidatorFillIdZeroFailureTest() throws Exception {
        ItemAvailableRequest request = new ItemAvailableRequest();

        // set ndc and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = new ArrayList<>();
        ndcs.add("1234");
        famIds.add(1234);

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);
        request.setKioskId(1);
        request.setQty(1);
        request.setSiteNbr(5550);
        request.setRxFillId(0);

        // call the custom validator method and verify the response
        assertEquals(false, itemAvailableRequestValidator.isValid(request, context));
    }

    /*
    test to verify the valid request with ndc null and required famId
     */
    @Test
    public void ItemsAvailableValidatorNullNdcSuccessTest() throws Exception {
        ItemAvailableRequest request = new ItemAvailableRequest();

        // set ndc and famId
        List<String> ndcs = null;
        List<Integer> famIds = new ArrayList<>();
        famIds.add(1234);

        // set fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);
        request.setQty(1);
        request.setSiteNbr(5550);
        request.setKioskId(5550);

        // call the custom validator method and verify the response
        assertTrue(itemAvailableRequestValidator.isValid(request, context));
    }


    /*
    test to verify the fail request with params to be null
     */
    @Test
    public void itemsAvailableValidatorNullFailureTest() throws Exception {
        ItemAvailableRequest request = new ItemAvailableRequest();

        // set ndc and famId
        List<String> ndcs = null;
        List<Integer> famIds = null;

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);

        // call the custom validator method and verify the response
        assertEquals(false, itemAvailableRequestValidator.isValid(request, context));
    }

    /*
    test to verify the valid request with empty ndc and valid famId
     */
    @Test
    public void itemsAvailableValidatorEmptyNdcSuccessTest() throws Exception {
        ItemAvailableRequest request = new ItemAvailableRequest();

        // set ndc and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = new ArrayList<>();
        famIds.add(1234);
        request.setQty(1);
        request.setSiteNbr(5550);
        request.setKioskId(5550);

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);

        // call the custom validator method and verify the response
        assertTrue(itemAvailableRequestValidator.isValid(request, context));
    }

    /*
        test to verify the fail request with all params to be empty
         */
    @Test
    public void ItemsAvailableValidatorEmptyFailureTest() throws Exception {
        ItemAvailableRequest request = new ItemAvailableRequest();

        // set ndc gpi and famId
        List<String> ndcs = new ArrayList<>();
        List<Integer> famIds = new ArrayList<>();

        // set goodRequest fields
        request.setNdc(ndcs);
        request.setMdsFamId(famIds);

        // call the custom validator method and verify the response
        assertEquals(false, itemAvailableRequestValidator.isValid(request, context));
    }

}
1

There are 1 best solutions below

3
On

You are mixing JUnit 4 org.junit.Before;, org.junit.Test and JUnit 5 org.junit.jupiter.*. This is causing the problems that you have.

@ParameterizedTest is from JUnit 5. So I suggest to use @BeforeEach and @BeforeAll and org.junit.jupiter.api.Test for @Test. Basically, drop all JUnit imports that are NOT org.junit.jupiter.* including the org.junit.Assert.*.

Here is one example that works with JUnit 5 and it uses @BeforeAll, @ParameterizedTest, @MethodSource, and @Test

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.stream.Stream;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class ParameterizedExampleTest {
    private final static String workgroup = "reporting";
    private final static String region = "eu-central-1";
    private final static String credentialsProviderArguments = "reporting";
    private Values values;

    private static Stream<Arguments> credentialProvidersWithCorrectArguments() {
        String webTokenProvider = "com.amazonaws.auth.WebIdentityTokenCredentialsProvider";
        String profileProvider = "com.amazonaws.auth.profile.ProfileCredentialsProvider";
        return Stream.of(
            Arguments.of(
                webTokenProvider,
                "jdbc:awsathena://AwsRegion=" + region + ";AwsCredentialsProviderClass=" + webTokenProvider + ";" +
                    "Workgroup=" + workgroup + ";LogLevel=6;"
            ),
            Arguments.of(
                profileProvider,
                "jdbc:awsathena://AwsRegion=" + region + ";AwsCredentialsProviderClass=" + profileProvider + ";" +
                    "AwsCredentialsProviderArguments=" + credentialsProviderArguments + ";Workgroup=" + workgroup +
                    ";LogLevel=6;"
            )
        );
    }

    @BeforeAll
    public void setup() {
        values = new Values();
        values.setAthenaRegion(region);
        values.setWorkgroup(workgroup);
        values.setDebugEnabled(true);
        values.setCredentialsProviderArguments(credentialsProviderArguments);
    }

    @ParameterizedTest
    @MethodSource("credentialProvidersWithCorrectArguments")
    void credentialsProviderHasCorrectCredentialsArguments(String credentialsProviderClass, String expected) {
        values.setCredentialsProviderClass(credentialsProviderClass);

        assertEquals(expected, values.getJdbcUrl());
    }

    @Test
    void wrongProviderClassThrowsException() {
        String credentialsProviderClass = "com.amazonaws.auth.WrongCredentialsProvider";
        values.setCredentialsProviderClass(credentialsProviderClass);

        try {
            values.getJdbcUrl();
            fail("An exception should be thrown to this method.");
        } catch (Exception e) {
            assertTrue(e.getMessage().contains("AWS credential class does not exist"));
        }
    }
}

Class being tested:

public class Values {
    private String athenaRegion;
    private String credentialsProviderClass;
    private String credentialsProviderArguments;
    private String jdbcDriverClass;
    private String databaseSchema;
    private String workgroup;
    private boolean debugEnabled;

    public String getJdbcUrl() {
        String athenaJdbcUrl = "jdbc:awsathena://AwsRegion=" + athenaRegion +
            ";AwsCredentialsProviderClass=" + credentialsProviderClass +
            (isProfileCredentialsProvider() ? ";AwsCredentialsProviderArguments=" + credentialsProviderArguments : "") +
            ";Workgroup=" + workgroup +
            (debugEnabled ? ";LogLevel=6;" : ";");

        LOG.debug("Athena connection URL: {}", athenaJdbcUrl);
        return athenaJdbcUrl;
    }

    private boolean isProfileCredentialsProvider() {
        try {
            return (Class.forName(credentialsProviderClass).isAssignableFrom(ProfileCredentialsProvider.class));
        } catch (ClassNotFoundException e) {
            throw new Exception("AWS credential class does not exist", e);
        }
    }
    // add GETTERS AND SETTERS ...
}