前言
如果您已经阅读了其他有关异常模拟的博客文章,则可以通过此链接跳过前奏 。
我被要求汇总一些示例,这些示例如何模拟因其可测试性问题而众所周知的Java结构:
- 模拟私人方法
- 模拟最终方法
- 模拟最后一堂课
- 模拟构造器
- 模拟静态方法
我称这些技术为异常嘲笑。 我担心这样的示例在没有任何指导的情况下会被在模拟框架方面没有丰富经验的队友广泛使用。
练习TDD或BDD的开发人员应意识到这些构造背后的可测试性问题,并在设计测试和模块时尽量避免它们。 这就是为什么您可能不会使用这些出色的编程方法在项目上经常遇到如此异常的模拟的原因。
但是有时您必须扩展或维护通常包含低内聚性类的旧代码库。 在大多数情况下,当前的忙碌敏捷世界没有时间使此类易于进行单元测试的标准方法。 当您尝试对此类进行单元测试时,您通常会意识到需要进行异常模拟。
这就是为什么我决定创建并共享重构注意事项以及异常模拟的示例和变通办法。 示例包括使用Mockito和PowerMock模拟框架以及TestNG单元测试框架。
模拟最后一堂课
重构注意事项
将类更改为非最终类(删除final关键字)并以标准方式对其进行测试。 这是我可以更改最终课程代码时始终使用的技术。
PowerMock的用法
在使用此示例之前,请仔细考虑是否值得在您的项目中带来字节码操作风险。 他们收集在此博客文章中 。 我认为,仅应在非常罕见且不可避免的情况下使用它。
测试显示了如何通过PowerMock框架模拟最终类。 示例涵盖:
- 在最终类中模拟具有返回值的方法
- 在最终课程中模拟最终void方法
- 验证最终类中的方法调用
期末课程:
public final class Plane {public static final int ENGINE_ID_RIGHT = 2;public static final int ENGINE_ID_LEFT = 1;public boolean verifyAllSystems() {throw new UnsupportedOperationException("Fail if not mocked!");}public void startEngine(int engineId) {throw new UnsupportedOperationException("Fail if not mocked! [engineId=" + engineId + "]");}
}
被测课程:
public class Pilot {private Plane plane;public Pilot(Plane plane) {this.plane = plane;}public boolean readyForFlight() {plane.startEngine(Plane.ENGINE_ID_LEFT);plane.startEngine(Plane.ENGINE_ID_RIGHT);return plane.verifyAllSystems();}
}
测试:
@PrepareForTest(Plane.class)
public class PilotTest extends PowerMockTestCase {@Testpublic void testReadyForFlight() {Plane planeMock = PowerMockito.mock(Plane.class);Pilot pilot = new Pilot(planeMock);Mockito.when(planeMock.verifyAllSystems()).thenReturn(true);// testing methodboolean actualStatus = pilot.readyForFlight();Assert.assertEquals(actualStatus, true);Mockito.verify(planeMock).startEngine(Plane.ENGINE_ID_LEFT);Mockito.verify(planeMock).startEngine(Plane.ENGINE_ID_RIGHT);}
}
链接
- 可以从Github下载源代码。
其他不寻常的嘲讽示例:
- 模拟私人方法
- 模拟最终方法
- 模拟构造器
- 模拟静态方法
翻译自: https://www.javacodegeeks.com/2014/02/mock-final-class.html