Java模拟返回null的私有字段的方法

时间:2017-03-15 05:23:17

标签: java junit mockito powermock powermockito

我正在尝试模拟返回类型为void的私有字段的方法。在我的测试中,我正在尝试模拟aClass.doSomething()以抛出IllegalStateException,我需要验证是否已调用recover()。这是一个例子:

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");
   }
}

我分别完成了每一件作品:

  1. 模拟私有字段的方法调用
  2. 模拟具有void返回类型
  3. 的方法
  4. 抛出异常
  5. 验证私人方法调用
  6. 但是我无法将所有内容放在一起。任何帮助表示赞赏

1 个答案:

答案 0 :(得分:2)

我以为我会详细说明GhostCat的评论:

  

留在Mockito

Mockito不仅仅是一个嘲弄框架 - 它还是一门学科。如果你仔细阅读了Mockito的文档并且不使用PowerMock et al ,那么你将学习很好的OOP练习。

  

阅读如何使用构造函数进行依赖注入

Primum non nocere - 首先重构您的代码:

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");
   }
}

现在您的代码可以使用Mockito 进行测试,而无需使用更复杂的模拟框架

//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"));
}