自己公司怎么做网站,月流量10g的网站,企业网站 自适应,重庆网站建设及优化点击上方蓝色字体#xff0c;选择“设为星标”回复”666“获取面试宝典TestableMock是基于源码和字节码增强的Java单元测试辅助工具#xff0c;包含以下功能#xff1a;访问被测类私有成员#xff1a;使单元测试能直接调用和访问被测类的私有成员#xff0c;解决私有成员初… 点击上方蓝色字体选择“设为星标”回复”666“获取面试宝典TestableMock是基于源码和字节码增强的Java单元测试辅助工具包含以下功能访问被测类私有成员使单元测试能直接调用和访问被测类的私有成员解决私有成员初始化和私有方法测试的问题快速Mock任意调用使被测类的任意方法调用快速替换为Mock方法实现指哪换哪解决传统Mock工具使用繁琐的问题辅助测试void方法利用Mock校验器对方法的内部逻辑进行检查解决无返回值方法难以实施单元测试的问题访问私有成员字段和方法如今关于私有方法是否应该做单元测试的争论正逐渐消停开发者的普遍实践已经给出事实答案。通过公有方法间接测私有方法在很多情况下难以进行开发者们更愿意通过修改方法可见性的办法来让原本私有的方法在测试用例中变得可测。此外在单元测试中时常会需要对被测对象进行特定的成员字段初始化但有时由于被测类的构造方法限制使得无法便捷的对这些字段进行赋值。那么能否在不破坏被测类型封装的情况下允许单元测试用例内的代码直接访问被测类的私有方法和成员字段呢TestableMock提供了两种简单的解决方案。方法一使用EnablePrivateAccess注解只需为测试类添加EnablePrivateAccess注解即可在测试用例中获得以下增强能力调用被测类的私有方法(包括静态方法)读取被测类的私有字段(包括静态字段)修改被测类的私有字段(包括静态字段)修改被测类的常量字段(使用final修饰的字段包括静态字段)访问和修改私有、常量成员时IDE可能会提示语法有误但编译器将能够正常运行测试。(使用编译期代码增强目前仅实现了Java语言的适配)效果见java-demo示例项目DemoPrivateAccessTest测试类中的用例。方法二使用PrivateAccessor工具类若不希望看到IDE的语法错误提醒或是在非Java语言的JVM工程(譬如Kotlin语言)里也可以借助PrivateAccessor工具类来直接访问私有成员。这个类提供了6个静态方法PrivateAccessor.get(被测对象, 私有字段名) ➜ 读取被测类的私有字段PrivateAccessor.set(被测对象, 私有字段名, 新的值) ➜ 修改被测类的私有字段(或常量字段)PrivateAccessor.invoke(被测对象, 私有方法名, 调用参数..) ➜ 调用被测类的私有方法PrivateAccessor.getStatic(被测类型, 私有静态字段名) ➜ 读取被测类的静态 私有字段PrivateAccessor.setStatic(被测类型, 私有静态字段名, 新的值)➜ 修改被测类的静态 私有字段(或静态 常量字段)PrivateAccessor.invokeStatic(被测类型, 私有静态方法名, 调用参数..) ➜ 调用被测类的静态 私有方法快速Mock被测类的任意方法调用相比以往Mock工具以类为粒度的Mock方式TestableMock允许用户直接定义需要Mock的单个方法并遵循约定优于配置的原则按照规则自动在测试运行时替换被测方法中的指定方法调用。归纳起来就两条Mock非构造方法拷贝原方法定义到测试类增加一个与调用者类型相同的参数加MockMethod注解Mock构造方法拷贝原方法定义到测试类返回值换成构造的类型方法名随意加MockContructor注解具体的Mock方法定义约定如下1. 覆写任意类的方法调用在测试类里定义一个有MockMethod注解的普通方法使它与需覆写的方法名称、参数、返回值类型完全一致然后在其参数列表首位再增加一个类型为该方法原本所属对象类型的参数。此时被测类中所有对该需覆写方法的调用将在单元测试运行时将自动被替换为对上述自定义Mock方法的调用。注意 当遇到待覆写方法有重名时可以将需覆写的方法名写到MockMethod注解的targetMethod参数里这样Mock方法自身就可以随意命名了。例如被测类中有一处anything.substring(1, 2)调用我们希望在运行测试的时候将它换成一个固定字符串则只需在测试类定义如下方法// 原方法签名为String substring(int, int)// 调用此方法的对象anything类型为String// 则Mock方法签名在其参数列表首位增加一个类型为String的参数(名字随意)// 此参数可用于获得当时的实际调用者的值和上下文MockMethodprivate String substring(String self, int i, int j) { return sub_string;}下面这个例子展示了targetMethod参数的用法其效果与上述示例相同// 使用targetMethod指定需Mock的方法名// 此方法本身现在可以随意命名但方法参数依然需要遵循相同的匹配规则MockMethod(targetMethod substring)private String use_any_mock_method_name(String self, int i, int j) { return sub_string;}完整代码示例见java-demo和kotlin-demo示例项目中的should_able_to_mock_common_method()测试用例。(由于Kotlin对String类型进行了魔改故Kotlin示例中将被测方法在BlackBox类里加了一层封装)2. 覆写被测类自身的成员方法有时候在对某些方法进行测试时希望将被测类自身的另外一些成员方法Mock掉。操作方法与前一种情况相同Mock方法的第一个参数类型需与被测类相同即可实现对被测类自身(不论是公有或私有)成员方法的覆写。例如被测类中有一个签名为String innerFunc(String)的私有方法我们希望在测试的时候将它替换掉则只需在测试类定义如下方法// 被测类型是DemoMock// 因此在定义Mock方法时在目标方法参数首位加一个类型为DemoMock的参数(名字随意)MockMethodprivate String innerFunc(DemoMock self, String text) { return mock_ text;}3. 覆写任意类的静态方法对于静态方法的Mock与普通方法相同。但需要注意的是静态方法的Mock方法被调用时传入的第一个参数实际值始终是null。例如在被测类中调用了BlackBox类型中的静态方法secretBox()改方法签名为BlackBox secretBox()则Mock方法如下// 目标静态方法定义在BlackBox类型中// 在定义Mock方法时在目标方法参数首位加一个类型为BlackBox的参数(名字随意)// 此参数仅用于标识目标类型实际传入值将始终为nullMockMethodprivate BlackBox secretBox(BlackBox ignore) { return new BlackBox(not_secret_box);}完整代码示例见java-demo和kotlin-demo示例项目中的should_able_to_mock_static_method()测试用例。测试无返回值的方法如何对void类型的方法进行测试一直是许多单元测试框架在悄悄回避的话题由于以往的单元测试手段主要是对被测单元的返回结果进行校验当遇到方法没有返回值时就会变得无从下手。从功能的角度来说虽然void方法不返回任何值但它的执行一定会对外界产生某些潜在影响我们将其称为方法的副作用比如初始化某些外部变量(私有成员变量或者全局静态变量)在方法体内对外部对象实例进行赋值输出了日志调用了其他外部方法… …不返回任何值也不产生任何副作用的方法没有存在的意义。这些副作用的本质归纳来说可分为两类修改外部变量 和调用外部方法 。通过TestableMock的私有字段访问和Mock校验器可以很方便的实现对副作用的结果检查。1. 修改外部变量的void方法例如下面这个方法会根据输入修改私有成员变量hashCacheclass Demo { private Map hashCache mapOf();public void updateCache(String domain, String key) { String cacheKey domain :: key; Integer num hashCache.get(cacheKey); hashCache.put(cacheKey, count null ? initHash(key) : nextHash(num, key)); } ... // 其他方法省略}若要测试此方法可以利用TestableMock直接读取私有成员变量的值对结果进行校验EnablePrivateAccess // 启用TestableMock的私有成员访问功能class DemoTest { private Demo demo new Demo(); Test public void testSaveToCache() { Integer firstVal demo.initHash(hello); // 访问私有方法 Integer nextVal demo.nextHash(firstVal, hello); // 访问私有方法 demo.saveToCache(demo, hello); assertEquals(firstVal, demo.hashCache.get(demo::hello)); // 读取私有变量 demo.saveToCache(demo, hello); assertEquals(nextVal, demo.hashCache.get(demo::hello)); // 读取私有变量 }}2. 调用外部方法的void方法例如下面这个方法会根据输入打印信息到控制台class Demo { public void recordAction(Action action) { SimpleDateFormat df new SimpleDateFormat(yyyy-MM-dd hh:mm:ss ); String timeStamp df.format(new Date()); System.out.println(timeStamp [ action.getType() ] action.getTarget()); }}若要测试此方法可以利用TestableMock快速Mock掉System.out.println方法。在Mock方法体里可以继续执行原调用(相当于并不影响本来方法功能仅用于做调用记录)也可以直接留空(相当于去除了原方法的副作用)。在执行完被测的void类型方法以后用InvokeVerifier.verify()校验传入的打印内容是否符合预期class DemoTest { private Demo demo new Demo(); // 拦截System.out.println调用 MockMethod public void println(PrintStream ps, String msg) { // 执行原调用 ps.println(msg); } Test public void testRecordAction() { Action action new Action(click, :download); demo.recordAction(); // 验证Mock方法println被调用且传入参数符合预期 verify(println).with(matches(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} \\[click\\] :download)); }}项目地址开源地址https://gitee.com/mirrors/TestableMock来源 | gitee.com/mirrors/TestableMock面试官问MySQL的自增ID用完了怎么办ArrayList插入1000w条数据之后我怀疑了jvm...蚂蚁二面面试官问我零拷贝的实现原理当场懵了…最近面试BAT整理一份面试资料《Java面试BAT通关手册》覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。获取方式点“在看”关注公众号并回复 666 领取更多内容陆续奉上。明天见(ω)♡