Check if a method was called inside another method
Asked Answered
B

4

5

Is there any way in java to check if a certain method was called inside another method? I am testing a class and the method I am having trouble with plays sound and there is virtually no way of getting the audio file that is played(private attribute inside an inner class) without changing the code. However the way the method plays sounds is it calls a method that plays a single sound (playSadMusic, playHappyMusic, etc). Those methods are in an interface that I have to create a mock object for. I'm a little stuck on how I would exactly go about testing this. Any thoughts? Any other ideas on how I could possibly test this other than check if a certain method was call are welcome.

I am using JMock 2.6.0 and JUnit 4

the audio inteface

public interface StockTickerAudioInterface {

    public abstract void playHappyMusic();

    public abstract void playSadMusic();

    public abstract void playErrorMusic();
}

anther interface I have to create a mock for

public interface StockQuoteGeneratorInterface {
    public abstract StockQuoteInterface getCurrentQuote() throws Exception;

    public abstract String getSymbol();

    public abstract void setSymbol(String symbol);

    public abstract StockQuoteGeneratorInterface createNewInstance(String symbol);

}

the class being tested

public class StockQuoteAnalyzer {
    private StockTickerAudioInterface audioPlayer = null;
    private String symbol;
    private StockQuoteGeneratorInterface stockQuoteSource = null;

    private StockQuoteInterface lastQuote = null;
    private StockQuoteInterface currentQuote = null;


    public StockQuoteAnalyzer(String symbol,
        StockQuoteGeneratorInterface stockQuoteSource,
        StockTickerAudioInterface audioPlayer)
        throws InvalidStockSymbolException, NullPointerException,
        StockTickerConnectionError {
        super(); 

    // Check the validity of the symbol.
        if (StockTickerListing.getSingleton().isValidTickerSymbol(symbol) == true){
            this.symbol = symbol;
        } else {
        throw new InvalidStockSymbolException("Symbol " + symbol
                + "not found.");
        }
        if (stockQuoteSource == null) {
             throw new NullPointerException(
                "The source for stock quotes can not be null");
        }
        this.stockQuoteSource = stockQuoteSource;
        this.audioPlayer = audioPlayer;
    }
    public double getChangeSinceLast() {
        double retVal = 0.0;
        if (this.lastQuote != null) {
            double delta = this.currentQuote.getLastTrade() - this.lastQuote.getLastTrade();
            retVal = 100 * (delta / this.lastQuote.getLastTrade());
           }
           return retVal;
    }

    public double getChangeSinceYesterday() {
        double delta = (this.currentQuote.getLastTrade() - this.currentQuote
            .getClose());
        return 100 * (delta / this.currentQuote.getClose());

    }

    public void playAppropriateAudio() {
        if ((this.getChangeSinceYesterday() > 2)
            || (this.getChangeSinceLast() > 0.5)) {
            audioPlayer.playHappyMusic();
    }

        if ((this.getChangeSinceYesterday() < -2)
            || (this.getChangeSinceLast() < -0.5)) {
            audioPlayer.playSadMusic();
        }
    }

}
Boccioni answered 15/5, 2013 at 7:17 Comment(5)
my crystal sphere says "yes" oh and please provide some code and say what you have tried so farHeaps
You can check the stack trace.Unidirectional
Follow John Snow. Mockito is the answer. You can create junit on how many times a method being called.Magdalenemagdalenian
I am using jmock2.6.0 and JUnit 4Boccioni
There seems to be able to achive similar behaviour with jMock. Check my edited postWhish
W
9

If you use Mockito you can use verify() to check the number of times a method was called. Use it like this:

verify(mockedObject, times(1)).methodToValidate();

You can check if methodToValidate() was called with a specific string, e.i verify(mockedObject, times(1)).methodToValidate("a specific value"); or you can use it with anyString() like this: verify(mockedObject, times(1)).methodToValidate(anyString());.

Unless this method is called with your specified paramterer, the test will fail

Read more about verify here.

UPDATE

Since your edited post states that you are using jMock, a quick googeling showed me that it is possible to achieve a similar behaviour with jMock and it's expect method. It's used as below:

mockedObject.expects(once()).method("nameOfMethod").with( eq("An optional paramter") );

More detailed explanation can be found by reading jMocks getting started page.

Whish answered 15/5, 2013 at 7:32 Comment(0)
Z
2

say you have a method child() which is called in parent()

public void parent() {
  child();
}

In child() to get the last method it got invoked from, you can use StackTraceElement

public void child() {
  StackTraceElement[] traces = Thread.currentThread().getStackTrace();
  boolean check = false;
      for(StackTraceElement element : traces) {
         if(check) {
            System.out.println("Calling method - " + element.getMethodName());
         }
         if(element.getMethodName().equals("child")) {
        check = true;
         }
      }
}
Zebu answered 15/5, 2013 at 7:26 Comment(0)
D
0

If you are writing a mock object with the methods you want to check whether they were called, you can implement the methods in a way they raise some flag when they are called, for example

public void playHappyMusic() {
    this.wasCalled = true;
}

wasCalled being a public (or with getters) class variable. Then you just check the flag.

Dalton answered 15/5, 2013 at 7:30 Comment(0)
A
-1

Provide you are in the same thread as the calling method, you can check the stack trace in any given moment this way:

Thread.currentThread().getStackTrace()

You can see what method are called doing it like this:

for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            System.out.println(ste);
        }

For example:

public class Test {

    public static void main (String[]s){
        Test  test = new Test();
        test.makeTest();
    }

    public void makeTest(){
        for (StackTraceElement ste : Thread.currentThread().getStackTrace()) {
            System.out.println(ste);
        }
    }

results in

java.lang.Thread.getStackTrace(Unknown Source)
Test.makeTest(Test.java:17)
Test.main(Test.java:11)
Antoninaantonino answered 15/5, 2013 at 7:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.