user3547204
user3547204

Reputation: 41

unit test - mockito testing to check if another method is invoked

Summary: I am trying to test if a method is invoked once I call one method.

What this class does is, displays information of wrong spelled words and provides u with buttons to 'ignore' or 'ignore all' or 'add to dictionary', etc.

Over here 'ignore' is a JButton declared above.

I am trying to write one test for this method ->

 public class SpellCheckerDialog extends JDialog implements ActionListener {

 ...
 ..

public void actionPerformed( ActionEvent ev ) {
    Object source = ev.getSource();
    if( source == ignore ) {
        searchNext();

    }
  }
 ...
}

Here is what it is invoking, I am testing to see if this method is being invoked or not.

...

//inside same class
public boolean searchNext() {
    String wordStr;
    while( true ) {
        wordStr = tok.nextInvalidWord();
        if( wordStr == null ) {
            dispose();
            String title = SpellChecker.getApplicationName();
            if(title == null){
                title = this.getTitle();
            }
            SpellChecker.getMessageHandler().handleInformation( getParent(), title, Utils.getResource( "msgFinish" ) );
            return false;
        }
        if( ignoreWords.contains( wordStr ) ) {
            continue;
        }
        String changeTo = changeWords.get( wordStr );
        if( changeTo != null ) {
            replaceWord( wordStr, changeTo );
            continue;
        }
        break;
    }
    word.setText( wordStr );
    notFound.setText( wordStr );

    List<Suggestion> list = dictionary.searchSuggestions( wordStr );

    boolean needCapitalization = tok.isFirstWordInSentence() && Utils.isFirstCapitalized( wordStr );

    Vector<String> suggestionsVector = new Vector<String>();
    for( int i = 0; i < list.size() && i < options.getSuggestionsLimitDialog(); i++ ) {
        Suggestion sugestion = list.get( i );
        String newWord = sugestion.getWord();
        if( needCapitalization ) {
            newWord = Utils.getCapitalized( newWord );
        }
        if( i == 0 )
            word.setText( newWord );
        suggestionsVector.add( newWord );
    }
    suggestionsList.setListData( suggestionsVector );

    addToDic.setEnabled( true );
    return true;
}

What I have tried until now, tried using Mockito and calling the verify method, but this code snippet seems to not working or have lots of dependencies that I am struggling to get around.

Inside my TestClass, I have this - >

    Dialog fr = Mockito.mock(Dialog.class);
    SpellCheckerDialog sD = new SpellCheckerDialog(fr);
    sD.searchNext();

    Mockito.verify(sD, Mockito.times(1)).thenReturn(searchNext());

I don't know if I should be making a stub for my (ActionEvent ev) or ...

Upvotes: 1

Views: 1808

Answers (1)

Morfic
Morfic

Reputation: 15518

Verifications must be done on the mocks created by Mockito, because the framework can't possibly know what happens with objects that it does not manage. This being said, your searchNext() method is part of your class under test so you probably want to spy on it just like in the example below:

public class SpyTest {

    class MyClass {

        public void callDoSomething(){
            doSomething();
        }

        public void doSomething(){
            // whatever
        }

    }

    @Test
    public void shouldSpyAndVerifyMethodCall(){
         MyClass objectUnderTest = new MyClass();
         MyClass spy = Mockito.spy(objectUnderTest);

        spy.callDoSomething();

        Mockito.verify(spy, Mockito.times(1)).doSomething();
    }
}

My advice is to go through the Mockito documentation and examples from the link above, as they're pretty straight-forward and should give you a good starting point.


EDIT as per your comment:

public class SpyTest {
    class MyClass {
        private JButton myButtton;

        public void actionPerformed(ActionEvent event){
            if(event.getSource() == myButtton) {
                searchNext();
            }
        }

        public void searchNext(){
            // whatever
        }
    }

    @Mock // define a mock for the button to "hack" the source check
    private JButton mockButton;

    @InjectMocks // inject the mock in our object under test
    private MyClass objectUnderTest;

    @Test
    public void shouldSpyAndVerifyMethodCall(){
        // spy on our object so we can query various interactions
        MyClass spy = spy(objectUnderTest);

        // event mock
        ActionEvent mockEvent = mock(ActionEvent.class);

        // "hack" the source check
        when(mockEvent.getSource()).thenReturn(mockButton);

        // call main logic
        spy.actionPerformed(mockEvent);


        // verify interactions
        verify(spy).searchNext();  // times(1) not needed because it's the implicit/default setting, see David's comment
    }
}

Upvotes: 1

Related Questions