简体   繁体   中英

Java mock a method of a private field that returns null

I am trying to mock a method of a private field that has a return type of void . In my test, I am trying to mock aClass.doSomething() to throw an IllegalStateException and I need to verify that recover() is called. Here is an example:

public class ClassToTest implements Runnable {
   private ClassToMock aClass;

   @Override
   public void run() {
       try{
           aClass.doSomething("some parameter");
       } catch(IllegalStateException e) {
           logger.error("Something bad happened", e);
           recover();
       }
   }

   public void recover(){
      logger.info("I am recovering");
   }
}

I have done each piece separately:

  1. Mock a method call of a private field
  2. Mock a method that has void return type
  3. Throw exception
  4. Verify a private method call

but I wasn't able to put all together. Any help is appreciated

I thought I'd elaborate GhostCat's comments:

Stay with Mockito

Mockito is more than a mocking framework - it's a discipline. If you read carefully the documentation for Mockito and restrain yourself from resorting to PowerMock et al you will learn good OOP practice.

Read how to do dependency injection with constructors

Primum non nocere - first refactor your code like this:

public class ClassToTest implements Runnable {

   private final ClassToMock aClass;
   private final Logger logger;

   //injection of collaborators through the constructor
   public ClassToTest(ClassToMock aClass, Logger logger) {
       this.aClass = aClass;
       this.logger = logger;
   }

   @Override
   public void run() {
       try{
           aClass.doSomething("some parameter");
       } catch(IllegalStateException e) {
           logger.error("Something bad happened", e);
           recover();
       }
   }

   public void recover() { //there is no need for this method to be public - see Effective Java item 13
      logger.info("I am recovering");
   }
}

Now your code is testable using Mockito without resorting to more complex mocking frameworks :

//mocks
@Mock ClassToMock classToMock;
@Mock Logger mockLogger;

//system under test
ClassToTest classToTest;

@Before
public void setUp() throws Exception { 
    MockitoAnnotations.initMocks();
    classToTest = new ClassToTest(classToMock, mockLogger);
}

@Test
public void whenRun_thenDoesSomethingWithSomeParameter() {       
    //act
    classToTest.run();

    //assert
    verify(classToMock).doSomething(eq("some parameter"));
}

@Test
public void givenAnIllegalStateForAClass_whenRun_thenLogsError() {       
    //arrange        
    IllegalStateException e = new IllegalStateException();
    when(classToMock.doSomething(anyString()).thenThrow(e); 

    //act
    classToTest.run();

    //assert
    verify(mockLogger).error(eq("Something bad happened"), same(e));
}

@Test
public void givenAnIllegalStateForAClass_whenRun_thenLogsRecovery() {       
    //arrange        
    when(classToMock.doSomething(anyString()).thenThrow(new IllegalStateException()); 

    //act
    classToTest.run();

    //assert
    verify(mockLogger).info(eq("I am recovering"));
}

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