0

I want to mock and test this Java code:

public class BusterClient {

    public BusterClient() {
    }

    @Autowired
    public BusterClient(PromoCodeService promoCodeService) {
        this.promoCodeService = promoCodeService;
    }

    private Optional<PromoCode> getPromoCode(CustomerRegistrationEvent event) {
        Optional<Long> campaignId = getCampaignIdAsLong(event);
        if (!event.hasPromoCode() || !campaignId.isPresent()) {
            return Optional.empty();
        }

        return promoCodeService.findByCampaignPromoCodeIds(campaignId.get(), event.getPromoCode());
    }
}

I created this test code:

@InjectMocks
private BusterClient app = new BusterClient();

@Test
public void testTrackedReferralNotMatchingPromoCode() throws Exception {
    
    PromoCodeService o = mock(PromoCodeService.class);
    when(o.findByCampaignPromoCodeIds(Long.valueOf(12), "test")).thenReturn(Optional.of(PromoCode.builder().id(Long.valueOf(1)).build()));

    try {

        Method method = BusterClient.class.getDeclaredMethod("getPromoCode", CustomerRegistrationEvent.class);
        method.setAccessible(true);
        method.invoke(app, customerRegistrationEvent);

    } catch (InvocationTargetException e) {
        e.getCause().printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

But I get error: promoCodeService.findByCampaignPromoCodeIds(java.lang.Long, String)" because "this.promoCodeService" is null

Do you know what is the proper way to mock PromoCodeService service?

Peter Penzov
  • 1,126
  • 134
  • 430
  • 808

2 Answers2

0

You must do something like this

    @Mock
    private PromoCodeService promoCodeService;
    @InjectMocks
    private BusterClient app;
    
      @BeforeEach
      void setUp() {
    
        MockitoAnnotations.initMocks(this);
      }
    
    @Test
    public void testTrackedReferralNotMatchingPromoCode() throws Exception {
        
        when(promoCodeService.findByCampaignPromoCodeIds(Long.valueOf(12), "test")).thenReturn(Optional.of(PromoCode.builder().id(Long.valueOf(1)).build()));
    
        ...
// Test a public method and not a private method. Use one public method that in turn will call your "getPromoCode".
    }
pringi
  • 3,987
  • 5
  • 35
  • 45
  • Thanks, now I get `Caused by: java.lang.UnsupportedOperationException: can't get field offset on a record class: private final java.lang.Long ....PromoCode.id` – Peter Penzov Oct 06 '22 at 15:30
0

Try to inject your mocked object into the client you are creating, and create the client in the test method instead of making it class variable

var app = new BusterClient(o); //where o is the object you created with mockito