junit test for methods calling another method of different class - java

I am writing Junit test for the below code using Mockito but I am getting a null pointer exception is there a mistake in the way I'm mocking it?
public boolean isApplyChecked()
{
return _rranalysis.getApplytoAllState();
}
and my test case is
#Test
public void testIsApplyChecked() {
JCheckBox Rra_Apply_Field = Mockito.mock(JCheckBox.class);
Mockito.when(Rra_Apply_Field.isSelected()).thenReturn(true);
RepeatRejectAnalysis rs = Mockito.mock(RepeatRejectAnalysis.class);
Mockito.when(rs.getApplytoAllState()).thenReturn(true);
boolean val = repeatRejectAnalysis_Listener.isApplyChecked();
Assert.assertEquals(true, val);
}

You have to inject the RepeatRejectAnalysis class dependency into your repeatRejectAnalysis_Listener. For example:
Use setter
RepeatRejectAnalysis rs =Mockito.mock(RepeatRejectAnalysis.class);
Mockito.when(rs.getApplytoAllState()).thenReturn(true);
repeatRejectAnalysis_Listener.setAnalysis(rs);
boolean val=repeatRejectAnalysis_Listener.isApplyChecked();
Use #InjectMocks
public class ListenerTest{
#InjectMocks
private Listener repeatRejectAnalysis_Listener = new Listener();
#Mock
private RepeatRejectAnalysis rs;
#Before
public void init(){
MockitoAnnotation.initMocks(this);
}
// reuse the exact same method as you have now.
#Test
public void testIsApplyChecked() {
JCheckBox Rra_Apply_Field=Mockito.mock(JCheckBox.class);
Mockito.when(Rra_Apply_Field.isSelected()).thenReturn(true);
RepeatRejectAnalysis rs =Mockito.mock(RepeatRejectAnalysis.class);
Mockito.when(rs.getApplytoAllState()).thenReturn(true);
boolean val=repeatRejectAnalysis_Listener.isApplyChecked();
Assert.assertEquals(true, val);
}
}

The other answer is correct about that one missing piece of mocking that you need. But then: none of the mocking that you have in your current test case seems to be required.
The idea of tests is to use a (minimal!) setup containing exactly those steps that are really mandatory to enable a test.
There is no point in mocking a JCheckBox ... when the method you intend to test doesnt make use of that check box in any way!

Related

How to mock the BooleanUtils class or an application property?

I'm trying to create a when sentence, but I can't do it well because I don't know how to mock correctly whatever.
I have this code:
public class OperationMovement {
#Value("${operation.check}")
private Boolean needToCheck;
private void checkOperation() {
// Code
if (BooleanUtils.isTrue(needToCheck)) {
// More code
}
}
}
I need to create a test with Mockito, but I don't know how to mock this if else.
I have tried to mock the BooleanUtils this way:
#Mock
BeanUtils beanUtils;
// Code and more testing code
when(booleanUtils.isTrue(anyBoolean())).thenReturn(true);
But this returs an error.
I have tried the following too, but I have the same error:
when(BooleanUtils.isTrue(anyBoolean())).thenReturn(true);
I need to mock that propertie or the BooleanUtils class, but I don't know how.
Quick example usage:
private OperationMovement classUnderTest;
...
#Test
void testOperationIsTrue() {
// For this test case, you are setting it to true
ReflectionTestUtils.setField(classUnderTest,"needToCheck",true);
}

Mockito - how to mock a variable instantiated in a method?

I have the following Java method:
public Appointment addAppointment(String client, Appointment appointment) {
String esbUrl = new ESBUrlHelper().getEsbUrl();
AppointmentClient appointmentClient = AppointmentClientFactory.getUnsecuredClient(esbUrl);
if (appointment.getId() == null) {
outputAppointment = appointmentClient.addAppointment(client, appointment);
}
return outputAppointment;
}
The method above makes a call to a third party REST client called appointmentClient.
The issue that I am having is that this is causing my test to fail.
How can I mock the appointmentClientobject within my unit tests?
Currently my test looks as follows:
#Test
public void shouldAddAppointment() {
// act
Appointment appointment = appointmentService.addAppointment(CLIENT_STRING, appointmentMock)
// assert
assertNotNull(appointment);
}
But I get the following error at line appointmentClient.addAppointment(client, appointment);:
org.jboss.resteasy.client.exception.ResteasyIOException: IOException
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
I want to mock something like as follows:
Mockito.when(appointmentClient.addAppointment(client, appointment)).thenReturn(appointmentMock);
You can try using PowerMockito for this.
First, you need to mock the static method call of AppointmentClientFactory class like below:
PowerMockito.mockStatic(AppointmentClientFactory.class);
PowerMockito.when(AppointmentClientFactory,"getUnsecuredClient",esbUrl).thenReturn(appointmentClient);
And also, when you use PowerMockito for mocking static methods, add the #PrepareForTest({AppointmentClientFactory.class}) annotation to the test class.
With your current code, the only way of mocking a call to AppointmentClientFactory#getUnsecuredClient would be using PowerMock, since the factory method is static. This is due to the hard coupling between your calling code addAppointment and the dependency here (i.e. the AppointmentClientFactory).
If I were you, I would avoid that as PowerMock is not the best way to do tests. Instead, what I would do, would be to inject the AppointmentClientFactory as a dependency thus allowing me to mock an instance of it during my tests.
This should be the best approach in twofold manner. Firstly, because you achieve less tightly coupled code and secondly because you do not need to use PowerMock for your unit-tests.
It's not impossible with Mockito. But your original problem is static method of AppointmentClientFactory. You definitely should change this method to the instance method (at least for better architecture) , for example:
public class AppointmentClientFactory {
public AppointmentClient getUnsecuredClient(String url) {
return new AppointmentClient(); //your implementation
}
}
Then your AppointmentService will look like (or close to it):
public class AppointmentService {
private final AppointmentClientFactory factory;
public AppointmentService() {
this(new AppointmentClientFactory());
}
public AppointmentService(AppointmentClientFactory factory) {
this.factory = factory;
}
public Appointment addAppointment(String client, Appointment appointment) {
String esbUrl = "";
Appointment outputAppointment = null;
AppointmentClient appointmentClient = new AppointmentClientFactory().getUnsecuredClient(esbUrl);
if (appointment.getId() == null) {
outputAppointment = appointmentClient.addAppointment(client, appointment);
}
return outputAppointment;
}
}
And then you will could write test like:
public class AppointmentTest {
private final String CLIENT_STRING = "";
#Test
public void shouldAddAppointment() {
AppointmentClientFactory clientFactory = Mockito.mock(AppointmentClientFactory.class);
AppointmentClient mockedClient = Mockito.mock(AppointmentClient.class);
AppointmentService service = new AppointmentService(clientFactory);
Appointment appointmentMock = new Appointment();
when(clientFactory.getUnsecuredClient(any())).thenReturn(mockedClient);
Appointment appointment = service.addAppointment(CLIENT_STRING, appointmentMock);
assertNotNull(appointment);
}
}

Why does this test pass?

I need your help to understand a unit (method) behaviors within a unit test class shown below.
public void updateAccount(Account account) {
if (!accountExists(account.getAccountNo())) {
throw new AccountNotFoundException();
}
accounts.put(account.getAccountNo(), account);
}
The method shown above tells me that the exception will be thrown if the account is not found
However the 2nd test ( updateNotExistedAccount) method shown below shows that it's expected that the method above (updateAccount ) should throw an exception to past the test. However, newAccount is already initialized /created within the createNewAccount so it exists already. So I assume that the updateNotExistedAccount will failed the test (because updateAccount won't throw exceptions in that case ), however updateNotExistedAccount passed.
public class InMemoryAccountDaoTests {
private static final String NEW_ACCOUNT_NO = "998";
private Account newAccount;
private InMemoryAccountDao accountDao;
#Before
public void init() {
newAccount = new Account(NEW_ACCOUNT_NO, 200);
accountDao = new InMemoryAccountDao();
}
#Test
public void createNewAccount() {
accountDao.createAccount(newAccount);
assertEquals(accountDao.findAccount(NEW_ACCOUNT_NO), newAccount); }
#Test(expected = AccountNotFoundException.class)
public void updateNotExistedAccount() { accountDao.updateAccount(newAccount);
}
Is it wrong if I assume updateNotExistedAccount will fail the test?
Seems like the data are persisted from one test to another.
Try to clean the data after each test.
#After
public void clean(){
// this method will be run after each single #Test method
// you can use this to clean all resoruces after a test. in your case for example
accountDao.deleteById(newAccount.getId());
}
For your test to be complete, and to test the update, I would do something like this:
#Test
public void updateExistingAccount() {
accountDao.createAccount(newAccount);
dbAccount = accountDao.findAccount(newAccount.getId);
dbAccount.setName("");
dbAccount.setSurname("");
// etc...
accountDao.updateAccount(dbAccount);
dbAccountUpdated = accountDao.findAccount(newAccount.getId);
assertEquals(accountDao.findAccount(dbAccountUpdated.getId()), dbAccount);
}
UPDATE
Consider also that #Before and #After runs respectively before and after each single test.
#BeforeClass and #AfterClass respectively before and after all tests.
With the use of these 4 methods you can start always the test with the desired dataset, and after the test clean everything as it were.
Please see:
Difference between #Before, #BeforeClass, #BeforeEach and #BeforeAll
To properly check need to look at your newAccount code as well as what all you are Mocking.
Check your #Before method as that will run before every #Test
Check if which test is running first when you run your suite

Mockito test in MVP pattern

I'm trying to unit test my Presenter class using Mockito and I always end up failing the test:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class java.lang.String
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
This is what my Presenter class looks like:
public class EditorPresenter implements EditorContract.Presenter {
private DataSource dataSourceImpl;
private EditorContract.View mView;
private SharedPreferences prefs;
EditorPresenter(SharedPreferences prefs,
DataSourceImpl dataSourceImpl,
EditorContract.View mView) {
this.dataSourceImpl = dataSourceImpl;
this.mView = mView;
this.prefs = prefs;
mView.setPresenter(this);
}
#Override
public void showNewNote() {
String noteColor = prefs.getString("default_note_color", "#ef5350");
String textColor = prefs.getString("default_text_color", "#000000");
mView.noteColor(Color.parseColor(noteColor));
mView.textColor(Color.parseColor(textColor));
}
}
And this is what I've done so far in EditorPresenterTest class:
public class EditorPresenterTest {
#Mock
private EditorContract.View mView;
#Mock
private DataSourceImpl mDataSourceImpl;
#Mock
private SharedPreferences sharedPrefs;
#Mock
private String noteColor;
#Mock
private String textColor;
#Before
public void setUpEditorPresenter() {
MockitoAnnotations.initMocks(this);
}
#Test
public void createEditorPresenter_newNote() {
EditorPresenter editorPresenter = new EditorPresenter(
sharedPrefs,
mDataSourceImpl,
mView);
verify(mView).setPresenter(editorPresenter);
}
#Test
public void showNewNote() {
when(sharedPrefs.getString(eq("default_note_color"), eq("#ef5350"))).thenReturn(noteColor);
when(sharedPrefs.getString(eq("default_text_color"), eq("#000000"))).thenReturn(textColor);
verify(mView).textColor(Color.parseColor(noteColor));
verify(mView).noteColor(Color.parseColor(textColor));
}
(Note: I'm new to Mockito and testing)
I have passed the createEditorPresenter_newNote() but the showNewNote() failed the test and shows error. Any Feedback/Answers are welcome. Hope someone helps me. Thanks!
I will first answer the exact question that you asked here but keep in mind that you have a larger issue that is hiding behind your compilation error, for which I will provide an answer right after.
(please keep in mind that I have no real experience with Android, so exact class names and use cases might not be valid, but your issues are more with understanding what test frameworks do and not syntax-oriented).
Your first issue is that you are trying to create mock types of the String class, which is final. As you can see in the error from Mockito:
Mockito cannot mock/spy following:
- final classes
In essence, there is no real reason for creating a mock of a String, because you are not testing String functionality. You can just use a constant.
if that is what you wish to fix, just remove the #Mock annotations from the noteColor and textColor variables and initialize them with some constant values.
More about testing frameworks and the other problems you are facing:
There is another major issue in your test case, and that is that you are trying to use the EditorPresenter you created in the first test inside the scope of the second test.
The thing is that test frameworks run different tests in separate states (rightfully so). So when you create the EditorPresenter instance inside the createEditorPresenter_newNote method, it won't be visible for you in the showNewNote test method, because it is a different process (not a different CPU process - just a process in the simple day-to-day term of the word).
What should you be doing instead?
That's what the before method is for: it will be called before every test runs, so you can set up shared functionality in one place.
what you should be doing is more on the line of this:
public class EditorPresenterTest {
#Mock
private EditorContract.View mView;
#Mock
private DataSourceImpl mDataSourceImpl;
#Mock
private SharedPreferences sharedPrefs;
private EditorPresenter editorPresenter;
#Before
public void setUpEditorPresenter() {
MockitoAnnotations.initMocks(this);
this.editorPresenter = new EditorPresenter(
sharedPrefs,
mDataSourceImpl,
mView);
}
#Test
public void createEditorPresenter_newNote() {
verify(mView).setPresenter(editorPresenter);
}
#Test
public void showNewNote() {
editorPresenter.showNewNote();
String noteColor = "#ef5350"; // or whatever color you want
String textColor = "#000000"; // or whatever color you want
when(sharedPrefs.getString(eq("default_note_color"), eq("#ef5350"))).thenReturn(noteColor);
when(sharedPrefs.getString(eq("default_text_color"), eq("#000000"))).thenReturn(textColor);
verify(mView).textColor(Color.parseColor(noteColor));
verify(mView).noteColor(Color.parseColor(textColor));
}
}

Use Powermockito to check if a private method is called or not

I would like to check if a private method of my class to test is executed or not using powermockito.
Suppose that I have this class to test:
public class ClassToTest {
public boolean methodToTest() {
//doSomething (maybe call privateMethod or maybeNot)
return true;
}
//I want to know if this is called or not during the test of "methodToTest".
private void privateMethod() {
//do something
}
}
When I test "methodToTest" I want to check if it returns the correct result but also if it executes the private method "privateMethod" or not.
Searching on other discussion I wrote this test that makes use of powermockito but it doesnt works.
public class TestClass {
#Test
testMethodToTest(){
ClassToTest instance = new ClassToTest();
boolean result = instance.methodToTest();
assertTrue(result, "The public method must return true");
//Checks if the public method "methodToTest" called "privateMethod" during its execution.
PowerMockito.verifyPrivate(instance, times(1)).invoke("privateMethod");
}
}
When I use the debugger it seems that the last line (PowerMockito.verifyPrivate...) doesn't check if the private method has been executed once during the test but instead it seems that it executes the private method itself. Furthermore the test passes but using the debugger I'm sure that the private method is not executed during the call of "instance.methodToTest()".
What is wrong?
I'd do it easier way, without PowerMockito. Consider this (it's some kind of Spy object):
public class TestClassToTest {
private boolean called = false;
#Test
public void testIfPrivateMethodCalled() throws Exception {
//given
ClassToTest classToTest = new ClassToTest() {
#Override
void privateMethod() {
called = true;
}
};
//when
classToTest.methodToTest();
//then
assertTrue(called);
}
}
This requires changing privateMethod() to package-private (but there's nothing wrong with this).
But bear in mind, that testing implementation is a bad practise and can lead to fragile tests. Instead you should test only results.

Categories