I am getting Wanted but not invoked. There were zero interactions with this mock error for checkFingerPrintWhenTouchIdEnabled()
method at line verify(fingerPrintHelper, times(1)).initializeFingerPrint(any());
.
Even I have mocked the object & while debugging initializeFingerPrint(..)
function gets called.
Below is the function which I want to test,
@RequiresApi(Build.VERSION_CODES.M)
public void checkFingerPrint() {
if (fingerPrintHelper.isDeviceReadyForFingerPrint()) {
boolean isFingerPrintEnable = sharedPreference.getBoolean(SpKeys.KEY_FINGER_PRINT, false);
if (isFingerPrintEnable) {
fingerPrintHelper.initializeFingerPrint(this);
}
} else {
sharedPreference.putBoolean(SpKeys.KEY_FINGER_PRINT, false).commit();
}
}
LoginActvity.java
public class LoginActivity extends AppCompatActivity {
public FingerPrintHelper fingerPrintHelper;
ActivityLoginBinding binding;
private LoginViewModel loginViewModel;
private SharedPreferenceManager sharedPreferenceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
sharedPreferenceManager = new SharedPreferenceManager(getApplicationContext(), SpKeys.MY_SP);
fingerPrintHelper = new FingerPrintHelper(this);
binding = DataBindingUtil.setContentView(this, R.layout.activity_login);
loginViewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
binding.setViewModel(loginViewModel);
binding.setLifecycleOwner(this);
checkFingerPrint();
}
@RequiresApi(Build.VERSION_CODES.M)
public void checkFingerPrint() {
if (fingerPrintHelper.isDeviceReadyForFingerPrint()) {
boolean isFingerPrintEnable = sharedPreferenceManager.getBoolean(SpKeys.KEY_FINGER_PRINT, false);
if (isFingerPrintEnable) {
fingerPrintHelper.initializeFingerPrint(this);
}
} else {
sharedPreferenceManager.setBoolean(SpKeys.KEY_FINGER_PRINT, false);
}
}
}
I am writing both positive and negative test cases for this function whereas checkFingerPrintWhenTouchIdDisabled()
test works fine, but I am getting error for checkFingerPrintWhenTouchIdEnabled()
test function
Please refer the below test class
LoginActivityTest.java
public class LoginActivityTest {
LoginActivity loginActivity;
@Mock
FingerPrintHelper fingerPrintHelper;
@Rule
public ActivityTestRule<LoginActivity> loginActivityRule = new ActivityTestRule<>(
LoginActivity.class);
Context context;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
loginActivity = loginActivityRule.getActivity();
context = getInstrumentation().getTargetContext();
}
@Test
public void checkFingerPrintWhenTouchIdDisabled() {
SharedPreferences sharedPreferences = context.getSharedPreferences(SpKeys.MY_SP, Context.MODE_PRIVATE);
when(fingerPrintHelper.isDeviceReadyForFingerPrint()).thenReturn(false);
loginActivity.checkFingerPrint();
Assert.assertFalse(sharedPreferences.getBoolean(SpKeys.KEY_FINGER_PRINT, false));
verify(fingerPrintHelper, never()).initializeFingerPrint(any());
}
@Test
public void checkFingerPrintWhenTouchIdEnabled() {
SharedPreferences sharedPreferences = context.getSharedPreferences(SpKeys.MY_SP, Context.MODE_PRIVATE);
SharedPreferences.Editor preferencesEditor = sharedPreferences.edit();
when(fingerPrintHelper.isDeviceReadyForFingerPrint()).thenReturn(true);
preferencesEditor.putBoolean(SpKeys.KEY_FINGER_PRINT, true).commit();
loginActivity.checkFingerPrint();
/* Below verification for `initializeFingerPrint()` is throwing error as,
Actually, there were zero interactions with this mock. error,
Even I have mock the object & while debugging the method is getting invoked also.
If I debug my code it calls this function but in test cases it shows above error
*/
verify(fingerPrintHelper, times(1)).initializeFingerPrint(any());
}
}
Then why am I getting the zero interaction error for my test cases? What could be the issue, any help is appreciated.
Thanks in advance.
Try the following to setup your mocks manually (without using annotations):
@Before
public void setUp() {
loginActivity = loginActivityRule.getActivity();
loginActivity.fingerPrintHelper = Mockito.mock(FingerPrintHelper.class);
// ...
}
If loginAcitivy
could be created succesfully before, you should not face a problem now.
And fingerPrintHelper
seems to be public
anyway so its easy to set.
But in case you want to do it properly you could just provide a setter.
Or if you want to keep the annotation to create fingerPrintHelper
.
@Mock
FingerPrintHelper fingerPrintHelper;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
loginActivity = loginActivityRule.getActivity();
loginActivity.fingerPrintHelper = fingerPrintHelper;
// ...
}
Still I would like to know the reason behind keeping loginActivity.fingerPrintHelper = fingerPrintHelper line.
A mock does not magically attach itself to any other object.
@InjectMocks
would do that for you, but Mockito does not seem be able to handle the creation of your LoginActivity
on its own.
So the only thing you can do is to manually pass the mock to the object under test.