Tarun Maganti
Tarun Maganti

Reputation: 3076

How to unit test to the case where there are two public methods, one calling another?

What is the way to test the methods when there are two public methods and a method calls another public method in the same class?

How should I write unit tests in this scenario?


An example

class SpecificIntMath {
   public int add(int a,int b) {
       return a+b;
   }
   public int multiply(int a, int b) {
       int mul = 0;
       for(int i = 0;i<b,i++) {
           mul=add(a,mul);
       }
       return mul;
   }
}

This example doesn't show the complexity of both the methods involved but the concept.

Should I test add and multiply separately? If I should test multiply only, I feel like we miss out cases where multiple cannot provide parameters.

Assuming multiply and add to be tested separately, should I be able to mock add? How is that possible?

Assuming multiply and add to be tested separately and I shouldn't mock, should I let add perform as it is. If this is the case how should I deal with the flow of the program inside add?

What is the approach to test such a kind of situation.


Edit 1:

In the below code,

class MCVC {
    public boolean getWhereFrom(List<User> users) {
        boolean allDone = true;
        for(User user: users){
            String url = user.getUrl();
            switch(url) {
                case Consts.GOOGLE:
                    someDao.updateFromAddr(user);
                    user.setEntry("Search Engine");
                    break;
                case Consts.FACEBOOK:
                    someDao.updateFromAddr(user);
                    user.setEntry("Social Media");
                    break;
                case Consts.HOME:
                    someDao.updateToAddr(user);
                    user.setEntry("Company");
                default
                    user.setEntry(null);
                    allDone = false;
                    break;
            }
        }
        return allDone;
    }

    public void likedDeck() {
        List<Users> usersList = deckDao.getPotentialUsers(345L,HttpStatus.OK);
        boolean flag = getWhereFrom(usersList);

        if(flag) {
            for(User user: usersList) {
                //some Action
            }
        }
    }
}

Should I consider getWhereFrom() while testing likedDeck() or should I assume any default situation? If I consider default situation, I lose out on cases where the output isn't default. I am not sure I should mock it since class which is calling is being tested. Spying/Mocking class under test

Upvotes: 2

Views: 1105

Answers (3)

GhostCat
GhostCat

Reputation: 140437

You don't care.

You use unit-testing to test the contract of each public method on its own. Thus you write tests that make sure that both add() and multiply() do what they are supposed to do.

The fact that the one uses the other internally is of no interest on the outside. Your tests should neither know nor care about this internal implementation detail.

And just for the record: as your code is written right now; you absolutely do not turn to mocking here. Mocking is not required here; and only adds the risk of testing something that has nothing to do with your real production code. You only use mocking for situations when you have to control aspects of objects in order to enable testing. But nothing in your example code needs mocking to be tested. And if it would - it would be an indication of poor design/implementation (given the contract of those methods)!

Edit; given the changes example in the question:

First of all, there is a bug in getWhereFrom() - you iterate a list; but you keep overwriting the return value in that list. So when the first iteration sets the result to false; that information might be lost in the next loop.

I see two options for the actual question:

  • You turn to Mockito; and its "spy" concept to do partial mocking; in case you want to keep your source code as is
  • Me, personally; I would rather invest time into improving the production code. It looks to me as getWhereFrom() could be worth its own class (where I would probably not have it work on a list of users; but just one user; that also helps with returning a single boolean value ;-). And when you do that, you can use dependency injection to acquire a (mocked) instance of that "WhereFromService" class.

In other words: the code you are showing could be reworked/refactored; for example to more clearly follow the SRP. But that is of course a larger undertaking; that you need to discuss with the people around you.

Upvotes: 3

Rodolfo
Rodolfo

Reputation: 511

Should I test add and multiply separately?

You should test them separately, if you are doing unit testing. You would only like to test them together when doing component or integration tests.

Assuming multiply and add to be tested separately, should I be able to mock add?

yes

How is that possible?

use mockito or any other mocking framework. Exactly how you can see here Use Mockito to mock some methods but not others

Assuming multiply and add to be tested separately and I shouldn't mock, should I let add perform as it is.

I wouldn't do that. Internal changes in add could affect the tests from multiply and your tests would get more complicated and unstable.

Upvotes: 0

Bgvv1983
Bgvv1983

Reputation: 1256

At least test them both seperatly. That the multiply test implicitly tests the add is no problem. In most of this cases you should ask yourself the question if it is necessary that both methods need to be public.

Upvotes: 0

Related Questions