首先是一些示例代码...

枚举:

public enum TestEnum {

YES,

NO

}

一些代码:

public static boolean WorkTheEnum(TestEnum theEnum) {

switch (theEnum) {

case YES:

return true;

case NO:

return false;

default:

// throws an exception here

}

}

问题:

我从其他开发人员的不同代码中导入了TestEnum。 因此它实际上可以改变。 对于这种情况,我想要一个单元测试来实际检查该不存在的值。 但是我根本不知道如何使用Mockito和JUnit做到这一点。

这部分当然不起作用:

@Test(expected=Exception.class)

public void DoesNotExist_throwsException() throws Exception {

when(TestEnum.MAYBE).thenReturn(TestEnum.MAYBE);

WorkTheEnum(TestEnum.MAYBE);

}

我找到了一个使用PowerMock的示例,但无法使其与Mockito一起使用。

有任何想法吗?

我没有足够的信心声称这是答案,但是:是否不可能做TestEnum notAValidEnum = Mockito.mock(TestEnum.class);,然后将其提供给WorkTheEnum() ...?

可能重复:stackoverflow.com/questions/5323505

可能相关:stackoverflow.com/questions/28013717/

以@assylias的答案为基础,我认为这是您可以做的最好的事情:

List unknown = new ArrayList<>();

for (TestEnum e : TestEnum.values())

unknown.add(e.name());

unknown.removeAll(Arrays.asList("YES","NO"));

if (unknown.isEmpty()) {

// Not possible to reach default case, do whatever you need to do

} else {

TestEnum notIncluded = TestEnum.valueOf(unknown.get(0));

workTheEnum(notIncluded);

}

由于enum switch语句的编译方式,不可能(AFAIK)伪造switch语句中不存在的enum值。即使您通过反射摆弄enum实例中的内部ordinal字段,switch语句也将给出ArrayIndexOutOfBoundsException而不是陷入default情况。

由于上面提到的ArrayIndexOutOfBoundsException,以下代码看起来可能可行,但无效:

TestEnum abused = TestEnum.YES;

try {

Class< ? > c = abused.getClass().getSuperclass();

Field[] declaredFields = c.getDeclaredFields();

Field ordinalField = null;

for (Field e : declaredFields) {

if (e.getName().equals("ordinal")) {

ordinalField = e;

}

}

ordinalField.setAccessible(true);

ordinalField.setInt(abused, TestEnum.values().length);

workTheEnum(abused);

} catch (Exception e) {

e.printStackTrace(System.err);

}

好的,这可能对您有用。这很hacky,所以对我来说,可能比没有100%代码覆盖率YMMV更糟糕。它通过用包含全零的数组替换枚举有序查找数组来工作,这属于默认情况。

// Setup values - needs to be called so that

// $SWITCH_TABLE$FooClass$BarEnum is initialised.

workTheEnum(TestEnum.YES);

workTheEnum(TestEnum.NO);

// This is the class with the switch statement in it.

Class< ? > c = ClassWithSwitchStatement.class;

// Find and change fields.

Map changedFields = new HashMap<>();

Field[] declaredFields = c.getDeclaredFields();

try {

for (Field f : declaredFields) {

if (f.getName().startsWith("$SWITCH_TABLE$")) {

f.setAccessible(true);

int[] table = (int[])f.get(null);

f.set(null, new int[table.length]);

changedFields.put(f, table);

}

}

workTheEnum(TestEnum.YES);

} finally {

for (Map.Entry entry : changedFields.entrySet()) {

try {

entry.getKey().set(null, entry.getValue());

} catch (Exception ex) {

ex.printStackTrace(System.err);

}

}

}

也许嘲笑不是正确的方法吗?但是必须有一种使用反射添加值的方法,以便枚举实际上是有效的并且具有所有这些值!

不,我不这么认为。编译switch语句时,将生成一个数组,其中包含该时间点存在的枚举值的所有序号。如果尝试修改现有值以更改其序数,则编译器生成的代码将访问数组范围之外的值,并失败并显示ArrayIndexOutOfBoundsException。糟糕的是附加了一些执行此操作的代码,以便您可以查看是否喜欢。

感谢您详细的答复@msandiford。我想运气不好。

对我来说,它仅在将f.setAccessible(true);添加到循环中时才有效(请参阅我的编辑)。这可能与Java8有关吗?

另一个注意事项:对我来说,它不适用于Maven(->在此排除它)。一旦Maven使用开关编译了该类,就必须再次在Eclipse中编译该类以使测试再次在Eclipse中工作。换句话说,无论测试是否有效,编译器都起着重要的作用。

一个简单的怎么样:

Set expected = new HashSet<> (Arrays.asList("YES","NO"));

Set actual = new HashSet<>();

for (TestEnum e : TestEnum.values()) actual.add(e.name());

assertEquals(expected, actual);

(使用HashSet而不是ArrayList,因为顺序无关紧要)

但这只会测试枚举的内容,而不会测试switch语句的默认路径。

我明白了-如果要达到默认大小写,您想确保该方法引发异常,因此您想模拟枚举以模拟非预期值。那正确吗?

那正是我想做的,是的。

@Feroc的问题是您无法通过反射实例化枚举的新实例,因此我不确定mockito是否可以解决该限制...

Mockito不支持枚举值的模拟,但powermock则支持。

尝试这个。

我创建了自己的类来模拟它们。请映射到您自己的班级。

@RunWith(PowerMockRunner.class)

@PrepareForTest(Trail.class)

public class TrailTest {

@Before

public void setUp() {

Trail mockTrail = PowerMock.createMock(Trail.class);

Whitebox.setInternalState(mockTrail,"name","Default");

Whitebox.setInternalState(mockTrail,"ordinal", 2);

PowerMock.mockStatic(Trail.class);

expect(Trail.values()).andReturn(new Trail[]{Trail.YES, Trail.NO, mockTrail});

expect(Trail.valueOf("default value")).andReturn(mockTrail);

PowerMock.replay(Trail.class);

}

@Test(expected = RuntimeException.class)

public void test() {

Trail aDefault = Trail.valueOf("default value");

BasicTrails.find(aDefault);

}

}

这是方法:

public class BasicTrails {

public static boolean find(Trail trail) {

switch (trail) {

case YES:

return true;

case NO:

return false;

default:

throw new RuntimeException("Invalid");

}

}

这是枚举

public enum Trail {

YES, NO;

}

谢谢你的帮助。不太确定我们是否可以在此处使用Powermock。

它只是另一个mock库。无论如何,这取决于选择。

如果您将代码转换为OP问题,则可以改善答案

@VinayVeluri:PowerMock不仅仅是另一个模拟库。它比Mockito更强大,这就是为什么有些人不想在项目中使用它的原因。它用于测试遗留代码,例如静态方法无法通过Mockito等"常规"模拟库进行测试。只要您开发一个新项目,就应该以不需要PowerMock的方式进行开发,但是Mockito就足够了。

借助Powermock,我们可以实现此目标,因为Powermock支持模拟最终类

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.mockito.BDDMockito;

import org.mockito.Mock;

import org.powermock.api.mockito.PowerMockito;

import org.powermock.core.classloader.annotations.PrepareForTest;

import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)

@PrepareForTest(Trail.class)

public class TrailTest {

@Mock Trail mockTrail;

@Before

public void setUp() {

PowerMockito.mockStatic(Trail.class);

BDDMockito.given(Trail.values()).willReturn(new Trail[]{Trail.YES, Trail.NO, mockTrail});

BDDMockito.given(Trail.valueOf("YES")).willReturn(mockTrail.YES);

BDDMockito.given(Trail.valueOf("NO")).willReturn(mockTrail.NO);

}

@Test

public void test() {

assertTrue(BasicTrails.find(mockTrail.valueOf("YES")));

assertFalse(BasicTrails.find(mockTrail.valueOf("NO")));

try{

Trail aDefault = mockTrail.valueOf("default value");

}catch (Exception e) {

System.out.println(e);

}

}

}

您可以嘲笑,修改或尝试使其工作,但是有一种非常简单的方法来做到这一点。我假设您正在使用Maven或Gradle,因此您具有main和test配置文件。

然后在主配置文件中,您将得到上面的代码:

package my.cool.package;

public enum TestEnum {

YES,

NO

}

但是在测试配置文件中,您可以拥有另一个:

// EXACTLY SAME as above

package my.cool.package;

public enum TestEnum {

YES,

NO,

INVALID_FOR_TEST_ONLY

}

现在您可以在测试中使用新值INVALID_FOR_TEST_ONLY,并且在产品概要文件中将不可用。

有两个缺点:

如果您更新产品枚举,则可能还需要更新测试(如果要进行测试,则需要更新)

某些IDE可能无法正确使用此技巧,即使Maven很好理解它

java 不识别enum_关于java:Unit Test for Enum值不存在?相关推荐

  1. java 音乐识别_使用java获取歌曲的属性

    今天使用java写了一个简单的android播放器,感觉还不错,就是向更加的完善一点上网搜索了一下获取音乐对象的属性,比如,作者,专辑,时间的大小.看到一个比较好的例子,贴出来给大家分享. publi ...

  2. java代码识别_识别Java中的代码气味

    java代码识别 作为软件开发人员,我们不仅要编写有效的代码,而且还要编写可维护的代码,这是我们的责任. Martin Fowler在他的<重构:改进现有代码的设计>中将代码气味定义为: ...

  3. Java中识别二维码并且提高二维码的识别率

    我们在Java开发的时候,发现对二维码的识别是不足的.所以我们需要提高识别率. 第一步.识别图片二维码.准备相应的jar包.我们在gradle+idea中开发. compile group: 'com ...

  4. java代码自动抠图_Opencv java实现人脸抠图和行为识别

    基于java的OpenCV环境搭建(Windows平台上ecplise) https://blog..net/qq_32447301/article/details/78494913 https:// ...

  5. Java 扫描识别条形码图片

    1.条形码扫描识别的实现方法及步骤 本文以Java代码示例介绍如何来扫描和识别条形码图片.这里使用免费的条码工具Free Spire.Barcode for Java,调用BarcodeScanner ...

  6. java人体识别_【人体分析-人像分割】JavaAPI示例代码

    接口能力: 对于输入的一张图片(可正常解码,且长宽比适宜),识别人体的轮廓范围,与背景进行分离,适用于拍照背景替换.照片合成.身体特效等场景.输入正常人像图片,返回分割后的二值结果图和分割类型(目前仅 ...

  7. java条码识别技术_Java 生成、识别条形码

    条形码是由一定的字符,数字及符号组成,用以表达一组信息的图形标识符.它可以标出物品的商品名称.生产日期.图书分类号,邮件起止地点等.因而在商品流通.图书管理.邮政管理等许多领域得以广泛的应用.本文将通 ...

  8. java ocr识别中文_java零碎要点—Tesseract 3.0,Java OCR 图像智能字符识别技术,可识别中文 | 学步园...

    2.Java OCR 图像智能字符识别技术,可识别中文 几天一直在研究OCR技术,据我了解的情况,国内最专业的OCR软件只有2家,清华TH-OCR和汉王OCR,看了很多的OCR 技术发现好多对英文与数 ...

  9. java ocr 识别中文

    几天一直在研究OCR技术,据我了解的情况,国内最专业的OCR软件只有2家,清华TH-OCR和汉王OCR,看了很多的OCR技术发现好多对英文与数字的支持都很好,可惜很多都不支持中文字符.Asprise- ...

最新文章

  1. MetagenoNets:在线宏基因组网络分析实操教程
  2. tensorflow-tf.train.shuffle_batch
  3. 数据类型,运算符和表达式02 - 零基础入门学习C语言03
  4. Python编程中一些异常处理的小技巧
  5. 【Jmeter篇】如何利用Jmeter配置元件计数器、随机变量制造批量数据和变量参数化?
  6. TreeView 之间节点拖动 /移动
  7. 【C++】max_element() 和 min_element()
  8. Learn OpenGL(五)——定义自己的着色器
  9. android c++标准命名空间demo
  10. mysql数据库原理与应用武洪萍第三张答案_MySQL数据库原理及应用(第2版)(微课版)...
  11. 怎么彻底删除mysql服务_mysql怎么卸载干净?
  12. 同志亦凡人第一季/全集BQueer As Folk 1迅雷下载
  13. 数据集成-3-数据集成框架
  14. Cydia Tweak
  15. java虚拟机 方法区_java虚拟机---方法区[szx]
  16. RGB转CMY最简单的方法
  17. 【DOM】DOM概述及DOM操作之如何查找元素_01
  18. 第000篇 - 一步一步了解区块链技术
  19. 智慧应管理信息化 平台建设方案
  20. 中国系统java开发面试准备

热门文章

  1. wxWidgets:wxListCtrl类用法
  2. wxWidgets:wxCalculateLayoutEvent类用法
  3. boost::mpi模块实现scan集合的测试
  4. boost::mp11::mp_partition_q相关用法的测试程序
  5. boost::describe模块宏BOOST_DESCRIBE_PP_IS_PAREN的测试程序
  6. ITK:向二进制图像添加噪声
  7. VTK:可视化之BackgroundGradient
  8. VTK:Utilities之Coordinate
  9. VTK:Math之PerpendicularVector
  10. VTK:几何对象之CellTypeSource