简体   繁体   中英

How can i mock an inherited method of the class i am testing

I have code similar to this

class Util{
 public String transform(String str);
 //lots of logic including ajax calls
 return("Modified"+str);
 }
 public caseChange(String str){
 //lots of logic including ajax calls
 return str.toUpperCase()      
 }

class TextParser extends Util{
 public String parse(str)
//lots of logic to modify str
 str = caseChange(str);
 //some more logic to modify str
return transform(str);
}

Is there anyway to mock the caseChange and transform methods to return some mocked data and prevent a call to the superclass when i call

String result = new TextParser().parse("hello")

in the unit test class to assert result.

The transform and changeCase are over simplified in my example. In reality they perform ajax calls and there is a ton of other logic. I want to mock them out so that can unit test just this part an then unit test the super methods later

In your given example: you simply don't do that. Your methods are only working on your inputs; so it should absolutely not matter where those methods are implemented.

In other words: it seems most appropriate for you to focus on contract checking tests only. Like:

@Test
public testWhatever() {
  assertThat(new TextParser.parse("hello"), is("expected output"));
}

Yes, you can probably mock such things using Mockito/Powermock; but you shouldn't! You see, your production code is directly calling those methods; so you want to test that calling parse gives you expected results (while using all the code that will also run in a production setup!)

Edit: given your comment about that methods being "complicated". Then I suggest: do not use inheritance here. You should not make class B a subclass of A just to have easy access to some methods. In other words: inheritance is about modeling an IS-A relation. So, a TextParser is a Util ? Doesn't sound very convincing.

Thus: you better turn to composition here. Your TextParser should use a Util object. And that one can be provided via dependency injection; and your need to mock with inherited methods vanishes completely!

You may need to create another subclass like

class TextParserForTest extends TextParser {
      @Override
      public String parse(String str)  {
              super.parse(str);
      }

      @Override
      public String caseChange(String str) {
              return "whatever";
      }
}

edit : use mockito to this :

import static org.mockito.Mockito.*;

import org.junit.Test;

@Test
public void test() {
    TextParser tp = mock(TextParser.class);

    // all the methods that you want to test
    when(tp.parse(any())).thenCallRealMethod();
    when... 

    // all the methods that you want to mock
    when(tp.caseChange(any()).thenReturn("whatever");
    when... 
}

You can use the spy functionality of Mockito. The spy calls real methods unless they are stubbed.

@Test
public void testParse() {   
    TextParser textParser = Mockito.spy(new TextParser());          
    when(textParser.caseChange(Matchers.anyString())).thenReturn("mocked");
    Assert.assertEquals("Modifiedmocked", textParser.parse("hello"));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM