Java模拟私有(private)字段的方法,返回null

标签 java junit mockito powermock powermockito

我正在尝试模拟返回类型为 void 的私有(private)字段的方法。在我的测试中,我尝试模拟 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. 模拟私有(private)字段的方法调用
  2. 模拟具有 void 返回类型的方法
  3. 抛出异常
  4. 验证私有(private)方法调用

但我无法将所有内容放在一起。任何帮助表示赞赏

最佳答案

我想我应该详细阐述 GhostCat 的评论:

Stay with Mockito

Mockito 不仅仅是一个模拟框架 - 它是一门学科。如果您仔细阅读 Mockito 的文档并克制自己不要诉诸 PowerMock ,您将学到良好的 OOP 实践。

Read how to do dependency injection with constructors

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

关于Java模拟私有(private)字段的方法,返回null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42801666/

相关文章:

Java - 沙漏

java - 警告登录之前

java - 执行错误 : org. infinispan.util.concurrent.TimeoutException:ISPN000299:10 秒后无法获取 key 的锁

java - 在每个单元测试之前创建 session

java - Mockito thenReturn() 返回空值

android - 如何使用任何模拟 Api for junit 模拟蓝牙适配器

java - 为什么 WebhookResponse 构建器在 json 中创建错误的 key ?

junit - 如何使 JUnit 测试按随机顺序运行?

java - 在函数中模拟私有(private)变量以测试 Junit4

java - 如何使用 Mockito 模拟 feign.Client.Default