【问题标题】:How to test default value in enum using mockito and testNg如何使用 mockito 和 testNg 测试枚举中的默认值
【发布时间】:2018-12-04 05:08:47
【问题描述】:

我有一个像这样的第三方枚举类:

package se.api;
public enum InvestigationResultStatus {
  PENDING("PendingResult.rr"),
  NEW("NewResult.rr"),
  MODIFIED("ModifiedResult.rr"),
  FINAL("FinalResult.rr"),
  PRELIMINARY("PreliminaryResult.rr"),
  ADDITIONAL("AdditionalResult.rr"),
  REJECTED("RejectedResult.rr"),
  COMPLETE("Path.Results.InvestigationInformation.Complete"),
  UNDEFINED("");

  private final String languageKey;

  private InvestigationResultStatus(String languageKey) {
    this.languageKey = languageKey;
  }

  public String getLanguageKey() {
    return this.languageKey;
  }
}

在我的代码中,我为这个类创建了枚举

package se.dto;
public enum InvestigationResultStatus
{
   PENDING,
   NEW,
   MODIFIED,
   FINAL,
   PRELIMINARY,
   ADDITIONAL,
   REJECTED,
   UNDEFINED
}

为了将这些 api 枚举映射到我的枚举,我创建了枚举映射器:

package se.mapper;

import se.dto.InvestigationResultStatus;

public class InvestigationResultStatusMapper
{
  public InvestigationResultStatus mapOmResultStatusToNovaResultStatus(final se.api.InvestigationResultStatus investigationResultStatus){
    switch (investigationResultStatus){
      case PENDING:
        return InvestigationResultStatus.PENDING;
      case NEW:
        return InvestigationResultStatus.NEW;
      case MODIFIED:
        return InvestigationResultStatus.MODIFIED;
      case FINAL:
        return InvestigationResultStatus.FINAL;
      case PRELIMINARY:
        return InvestigationResultStatus.PRELIMINARY;
      case ADDITIONAL:
        return InvestigationResultStatus.ADDITIONAL;
      case REJECTED:
        return InvestigationResultStatus.REJECTED;
      case UNDEFINED:
        return InvestigationResultStatus.UNDEFINED;
      default:
        throw new IllegalArgumentException("Unknown InvestigationResultStatus: " + investigationResultStatus);
    }
  }
}

现在我想测试 InvestigationResultStatusMapper 类的默认案例路径并抛出 IllegalArgumentException。我以多种方式搜索并尝试它。但大多数示例都在使用 powermockito。但我想要带有 testNg 的 mackito。我该如何测试它。我用这个尝试它,

@Test(expectedExceptions = { IllegalArgumentException.class })
  public void testMapOmResultStatusToNovaResultStatus_whenHaveDefaultValue_thenThrowIllegalArgumentException()
  {
    se.api.InvestigationResultStatus investigationResultStatusNewEnum = mock(se.api.InvestigationResultStatus.class);
    Whitebox.setInternalState(investigationResultStatusNewEnum, "name", "DEFAULT");
    Whitebox.setInternalState(investigationResultStatusNewEnum, "ordinal", "DefaultResult.rr");

    se.api.InvestigationResultStatus investigationResultStatusCosmic = mock(se.api.InvestigationResultStatus.class);

    when(investigationResultStatusCosmic.values()).thenReturn(
        new se.api.InvestigationResultStatus[] { InvestigationResultStatus.PENDING, InvestigationResultStatus.NEW,
            se.api.InvestigationResultStatus.MODIFIED, InvestigationResultStatus.FINAL, InvestigationResultStatus.PRELIMINARY,
            se.api.InvestigationResultStatus.ADDITIONAL, InvestigationResultStatus.REJECTED,
            se.api.InvestigationResultStatus.COMPLETE, InvestigationResultStatus.UNDEFINED, investigationResultStatusNewEnum });

    investigationResultStatusMapper.mapOmResultStatusToNovaResultStatus(investigationResultStatusNewEnum);
  }

【问题讨论】:

  • 我仍然有错误。因此我转向 powermock 并模拟它。没有从 mockito 得到任何解决方案
  • 如前所述:您编写了很难测试生产代码。你现在开始使用 powermock 的事实......基本上意味着你对抗症状,而不是根本原因。请放心:从长远来看,您可以通过投资改进设计来提高效率,而不是使用更奇怪的模拟框架来解决由您的设计引起的问题。

标签: java unit-testing enums mockito testng


【解决方案1】:

您可以直接创建一个实例以避免模拟。

@Test(expectedExceptions = { IllegalArgumentException.class })
public void testMapOmResultStatusToNovaResultStatus_whenHaveDefaultValue_thenThrowIllegalArgumentException()
{

  InvestigationResultStatus investigation = new InvestigationResultStatus();
  investigation.mapOmResultStatusToNovaResultStatus(-10000);
   ....

}

【讨论】:

  • 下一个软,是的!但我想通过传递不在我的枚举中的值来测试默认情况。这就是我嘲笑 Enum 类的情况。
  • 我更新了我的答案,你可以这样做以抛出 IllegalArgumentException。 @JayaniSumudini
  • 下一个软,我已经有一个测试空的测试用例,@Test(expectedExceptions = { NullPointerException.class }) public void testMapOmResultStatusToNovaResultStatus_whenHaveNull_thenThrowNullPointerException() { InvestigationResultStatusMapper.mapOmResultStatusToNovaResultStatus(null); } 但它返回 NullPointerException。不是 IllegalArgumentException。我想测试默认案例路径。
  • :V 对不起,我不明白 .. 你的意思
  • 默认值?在您的课程中,我没有看到您默认设置了一些值,您需要测试一些已设置的值。例如:class A { setEnum(Type.DEFAULT_VALUE)} 所以对 A 类进行测试,A a = new A(); a.getEnumValue();所以默认情况下你会有一个值。
【解决方案2】:

在此我无法使用 mockito 模拟 enum(final) 类

 @BeforeClass
  public void setUp()
  {
    investigationResultStatusMapper = new InvestigationResultStatusMapper();
    investigationResultStatusNewEnum = PowerMockito.mock(InvestigationResultStatus.class);


    Whitebox.setInternalState(investigationResultStatusNewEnum, "name", "TEST");
    Whitebox.setInternalState(investigationResultStatusNewEnum, "ordinal", 9);

    InvestigationResultStatus[] investigationResultStatuses = Arrays
        .copyOf(InvestigationResultStatus.values(), InvestigationResultStatus.values().length + 1);
    investigationResultStatuses[investigationResultStatuses.length - 1] = investigationResultStatusNewEnum;

    PowerMockito.mockStatic(InvestigationResultStatus.class);

    PowerMockito.when(InvestigationResultStatus.values()).thenReturn(
        investigationResultStatuses);
  }

  /**
   * Test Method for {@link InvestigationResultStatusMapper#mapOmResultStatusToNovaResultStatus(InvestigationResultStatus)}
   * extend the InvestigationResultStatus enum for DEFAULT throw {@link IllegalArgumentException})
   */
  @Test(expectedExceptions = {
      IllegalArgumentException.class }, expectedExceptionsMessageRegExp = "Unknown InvestigationResultStatus: TEST")
  public void testMapOmResultStatusToNovaResultStatus_whenHaveDefaultValue_thenThrowIllegalArgumentException()
  {
    investigationResultStatusMapper.mapOmResultStatusToNovaResultStatus(investigationResultStatusNewEnum);
  }

【讨论】:

  • 老实说,这不是一个好的自我回答。你至少应该添加一些解释你到底做了什么。您刚刚更改为 PowerMock 的事实并不是很明显,更糟糕的是:正如您自己所说:它没有回答您的真正问题,因为您最初没有询问 powermock。
【解决方案3】:

错误的方法。首先,第 3 方枚举有 9 个条目,但您自己的枚举只有 8。因此,当您的映射代码收到COMPLETE 时,它会抛出该异常!但是,如果您自己的枚举有 9 个条目,而您只是将它们 1-1 映射……首先在这里使用您自己的枚举有什么意义? (可能有充分的理由拥有它,但在这一点上,它并没有增加太多价值)。

除了这个问题,你应该做完全不同的事情:

您将这些 映射 放入 Map 对象中。然后编写一个单元测试,使用InvestigationResultStatus.values() 获取一个包含所有valid InvestigationResultStatus 常量的数组。您确保您的地图知道如何映射所有这些有效常量(例如,通过检查您是否获得了非空返回值)。此外,您可能会对每个第 3 方常量进行一次测试,以检查预期结果。

这里的关键点是:不幸的是,枚举可能会随着时间而改变。因此,您绝对想知道何时将其他常量添加到第三个枚举中。

换句话说:Java 语言分别是编译器确保第三方枚举不能有“无效”实例。当您拥有InvestigationResultStatus someEnumValue 时,100% 清楚:someValue 为空,或者它是该枚举中的常量之一。这里没有其他可能!因此:无需期待、检查或处理“无效”值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2016-10-10
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    相关资源
    最近更新 更多