Tioma
Tioma

Reputation: 2150

How to properly test internal method of class in java

How can I test the following code?

class1 {

    public InjectedClass injectedClass; 

    method1(){
        returnValue = injectedClass.someMethod; 
        //another logic
    }

    method2(){
        resultValue = method1();
    }

}

My application was developed in Java. I use JUnit and Mockito.

To test method1() I can create a mock for InjectedClass and a mock logic for someMethod(). But how does one properly test a method? Do I need to create a mock for method1()?

UPDATE: Let me demonstrate real example.

public class Application { 

@Inject 
DAOFacade facade;

//method1 
 public ReturnDTO getDTO(LiveServiceRequestParam requestParam) throws AffiliateIdentityException {
        ReturnDTO returnDTO  = new ReturnDTO();

        CoreProductRepository repo = recognizeProduct(ProdCodeTypeEnum.MPN, null, vendorBound);
        if(repo!=null){
           //logic to fill some fileds in returnDTO  
        }

        return returnDTO  ;
    }

//метод2 
 CoreProductRepository recognizeProduct(ProdCodeTypeEnum paramType, String prodCode, List<Integer> vendors) {
        CoreProductRepository coreProductRepository = null;
        switch (paramType) {
            case MPN:
                coreProductRepository = facade.findByAlternativeMPN(prodCode, vendors);
                break;
            case EAN:
                coreProductRepository = facade.findByEan(prodCode, vendors);
                break;
            case DESCRIPTION:
                coreProductRepository = facade.findByName(prodCode, vendors);
                break;
        }
        return coreProductRepository;
    }
}

So, to test recognizeProduct i mock DAOfacade. But also I want test getDTO method which uses recognizeProduct method.

Upvotes: 2

Views: 1017

Answers (4)

soru
soru

Reputation: 5526

It seems to me you have a (sadly common) misunderstanding of the word test; it does not mean 'execute from a test case'.

Testing means supplying a range of inputs, and asserting that the corresponding outputs are correct. 99% of the time that means checking return codes or object state, occasionally you have to use mocks to properly test a pure-output interface.

If you do that for the public methods, and the private methods are fully covered to the required standard, job done. If there is uncovered code in private methods, either use it to identify and add a missing test case, or delete it.

In the event you feel there would be something useful lost by deleting unreachable private code, make it public, or move it out to another class.

Upvotes: 1

Dima
Dima

Reputation: 40500

You don't need to mock out your recognizeProduct method. As long as the DAOfacade is mocked, the behavior is known and deterministic, so the results of both getDTO and recognizeProduct can be verified.

It can also be argued, that you don't even need to test recognizeProduct specifically, because it is not public, so, there is no contract to enforce. As long as the behavior of getDTO is being tested and verified, your API is working as far as the user is concerned. The details of implementation aren't important.

In a way, testing recognizeProduct specifically is counter-productive, it hurts the maintainability and reliability of your code rather than helping it, because it makes any refactoring or reorganization harder to achieve even if it does not affect the externally visible behavior in any way.

Upvotes: 2

Claudio Redi
Claudio Redi

Reputation: 68400

You should focus your test effort on public methods return value and not not on internal implementation.

Focusing on internal implementation causes tests to be harder to mantain since a basic refactoring not affecting the return value will probably require changing your tests.

Sometimes is impossible to avoid testing internal implementation since some methods return nothing and you need to "assert" something. In this case it seems you return something at some point, I'd focus on testing that.

Upvotes: 1

blalasaadri
blalasaadri

Reputation: 6198

If the methods are defined as shown in your example, they are package private. So, if you create a test in the same package (though normally in a test directory) you will be able to access those methods and test them.

That said, if you can refactor or rewrite the class to be more easily testable then that might be a good idea. If indeed you have to test the results of the internal methods and can't just test public ones.

Upvotes: 1

Related Questions