Sindhu
Sindhu

Reputation: 451

Unit testing a function that is calling another static function in android java using Mockito

I have a scenario where I call a static function from another function. How can we write unit tests in such cases?

Here is my code:

public class TradesHelper {

public static double calculatePL(Market market, Trade trade) {
    double pl = (Helper.priceDifference(market, trade) / market.getSize()) * trade.getQuantity() * Helper.effectiveValue(market);
    return pl;
    }
}

public class Helper {
public static priceDifference(Market market, Trade trade) {
           //Do something here
      }
}

This is how I am trying to write unit test case:

I have written a unit test case for Helper class. But for TradesHelper class this is how I am trying to write:

public class TradesHelperTest {

@Mock
Market market;

@Mock
Trade trade;

@Test
public void calculatePlFromPips_Test() {

    //Trying to return a value when priceDifference function in Helper class is called

    Helper helper1 = spy(new Helper());     
    doReturn(0.0012999999999999678).when(helper1).priceDifference(new Market(),new Trade());   

}

But I am getting thus error:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
Unfinished stubbing detected here:

E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3: you are stubbing the behaviour of another mock inside before      'thenReturn' instruction if completed

I am new to writing unit tests. Can someone guide me on how to do it write?

Thanks

Upvotes: 0

Views: 717

Answers (1)

Timothy Truckle
Timothy Truckle

Reputation: 15624

As the comments tell you cannot mock static methods with pure "vanilla" Mockito.

But static access is a bad design and should be avoided. You problem creating a test is the prove that static access makes the code using tightly coupled and therefor hard to reuse (since testing is kind of "reuse"...). Static access also effectively prohibits inheritance and polymorphism, two major concepts why we are using an OO language.

On the other hand there is not rule that "helper classes" or "utility classes" (in the sense that they provide common behavior) must have static methods. This is only a misconception because classes with only static methods used to be called "utility classes".

So instead of surrendering to your bad design and using Powermock you should change both class Helper and class TradesHelper to have non static methods and use objects of them in your production code.
Java is an object oriented programming language after all, so why avoiding objects?

But do not instantiate Helper inside TradesHelper. Pass the instance of Helper in as a constructor parameter:

public class TradesHelper {
   private final Helper helper;
   public TradesHelper(Helper helper){
      this.helper = helper;
   } 
   public double calculatePL(Market market, Trade trade) {
   // ...

public class TradesHelperTest {

    @Mock
    Market market;

    @Mock
    Trade trade;

    @Mock
    private Helper helper;

    private TradesHelper tradesHelper; // class under test, no mock nor spy!

    @Before
    public void setup(){
      tradesHelper= new TradeHelper(helper);
    }

    @Test
    public void calculatePlFromPips_Test() {
        // arrange
        doReturn(0.0012999999999999678)
             .when(helper)
             .priceDifference(market,trade);// use mocks here not new objects

        // act
        tradesHelper.calculatePL(market,trade);


       // assert 
       // either assertThat() or verify()
    }
}

Upvotes: 1

Related Questions