java - 使用 PowerMock 模拟链式方法调用

标签 java unit-testing junit mockito powermock

我有一个类,我想使用包含一些链式方法调用的公共(public)静态方法进行测试。假设在链式方法调用期间发生异常,我如何有效地处理该异常并使其返回某个特定值?

以下是测试类的代码示例。

@RunWith(PowerMockRunner.class)
@PrepareForTest({CodeWithPrivateMethod.class,CodeWithAnotherPrivateMethod.class,CodeWithYetAnotherPrivateMethod.class})
public class CodeWithPrivateMethodTest {

@Test
public void when_gambling_is_true_then_always_explode() throws Exception {


    CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = PowerMockito.spy(new CodeWithYetAnotherPrivateMethod());
    PowerMockito.whenNew(CodeWithYetAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithYetAnotherPrivateMethod);

    CodeWithAnotherPrivateMethod codeWithAnotherPrivateMethod = PowerMockito.spy(new CodeWithAnotherPrivateMethod());
    PowerMockito.whenNew(CodeWithAnotherPrivateMethod.class).withAnyArguments().thenReturn(codeWithAnotherPrivateMethod);

    PowerMockito.doReturn(true).when(codeWithYetAnotherPrivateMethod, "getGambling");

    //PowerMockito.doReturn(codeWithYetAnotherPrivateMethod).when(codeWithAnotherPrivateMethod, "getGambleValue");

    PowerMockito.spy(CodeWithPrivateMethod.class);
    CodeWithPrivateMethod.startGamble();

    }

}

以下是被测类的代码示例

public class CodeWithPrivateMethod {

public static void startGamble() {

    Boolean gamble = CodeWithAnotherPrivateMethod.getGambleValue()
            .getGambling();
    if (gamble) {
        System.out.println("kaboom");
    }else{
        System.out.println("boom boom");
    }
    }
}

以下是从被测类调用的类的代码示例

public class CodeWithAnotherPrivateMethod {

static CodeWithYetAnotherPrivateMethod codeWithYetAnotherPrivateMethod = new CodeWithYetAnotherPrivateMethod();


public static CodeWithYetAnotherPrivateMethod getGambleValue() {
    return codeWithYetAnotherPrivateMethod; //works fine
    return null; // fails
    }
}

以下是从被测类调用的另一个类的代码示例

public class CodeWithYetAnotherPrivateMethod {

public Boolean getGambling() {
    return false;
    }
}

假设我从 CodeWithAnotherPrivateMethod 类的 getGambleValue() 方法返回一个空值,我如何在我的测试类中有效地处理这个空值?

最佳答案

这是使用 Mockito 指定预期异常的方法:

@Test(expected = NullPointerException.class)
public void when_gambling_is_true_then_always_explode() throws Exception {
    ...

在我发现这一点之前,我会这样做:

@Test
public void when_gambling_is_true_then_always_explode() throws Exception {
    // setup omitted
    try {
        CodeWithPrivateMethod.startGamble();
    } 
    catch(NullPointerException e) {
        // expected
        return;
    }
    fail("Expected NullPointerException");
}

编辑:测试像这样静态地相互调用的多个类是一种严重的代码味道。单元测试应测试单个类,内联静态调用应仅限于实用程序类。

另一条评论:你的示例类名非常困惑。下次请坚持使用 Foo、Bar、Baz 或 Apple、Pear、Banana。

如果您没有获得 NPE,那么我预计您的 mock / spy 行为会造成干扰。如果您在不模拟/监视的情况下调用被测代码,则调用链将是:

CodeWithPrivateMethod.startGamble();
->
CodeWithYetAnotherPrivateMethod value = CodeWithAnotherPrivateMethod.getGambleValue();
-> 
return null;
<-
value.getGambling();
<- throws NullPointerException

您到底想找出或实现什么?

编辑:这是它应该如何与 PowerMock 一起工作

@RunWith(PowerMockRunner.class)
@PrepareForTest(CodeWithAnotherPrivateMethod.class)
public class CodeWithPrivateMethodTest {

  @Mock
  private CodeWithYetAnotherPrivateMethod yetAnotherInstance;

  @Test
  public final void testStartGamble() {

    // SETUP
    mockStatic(CodeWithAnotherPrivateMethod.class);
    expect(CodeWithAnotherPrivateMethod.getGambleValue())
        .andReturn(yetAnotherInstance);
    Boolean gamblingValue = true;
    expect(yetAnotherInstance.getGambling()).andReturn(gamblingValue);
    replayAll();

    // CALL
    CodeWithPrivateMethod.startGamble();

    // VERIFY
    verifyAll();
  }

关于java - 使用 PowerMock 模拟链式方法调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35574111/

相关文章:

java - 在 Junit5 中为每个测试设置环境变量

java - JUnit 4 断言中的 "is"

Java 11 `HttpClient` 下载但没有? (负内容长度)

java - 了解 Java 中的本地类

python - 导入错误: No module named 'app'

android - ShadowAlertDialog.getLatestAlertDialog() 为 android.support.v7.app.AlertDialog 返回 null

ios - 在 Xcode 机器人上运行单元测试后生成 .gcda 文件

java - Set<字符串> getSet(字符串 s)

java - Matlab 中的 GZIP 用于大文件

java - 创建http响应作为mockito的返回值