Mockito –带有注释和静态方法的额外接口

在代码中,我最近遇到了一段非常糟糕的代码,这些代码基于对对象执行某些操作的类转换。 当然,代码需要重构,但是如果您首先没有对该功能进行单元测试,则有时您可能无法做到/或者不想这样做(这应该是可以理解的)。 在下面的文章中,我将展示如何测试这种代码,如何重构它以及实际上我对这种代码的看法。

让我们看一下项目结构:

如关于Mocktio的JAXB答复REPOSTS_DEEP_STUBS的帖子所述,在com.blogspot.toomuchcoding.model包中,我们再次使用JAXB编译器生成了JAXB生成的类。 让我们省略对pom.xml文件的讨论,因为它与上一篇文章完全相同。

com.blogspot.toomuchcoding.adapter包中,我们在JAXB PlayerDetails类上具有适配器,该类提供对Player接口的访问。 有:

CommonPlayerAdapter.java

package com.blogspot.toomuchcoding.adapter;import com.blogspot.toomuchcoding.model.Player;
import com.blogspot.toomuchcoding.model.PlayerDetails;/*** User: mgrzejszczak* Date: 09.06.13* Time: 15:42*/
public class CommonPlayerAdapter implements Player {private final PlayerDetails playerDetails;public CommonPlayerAdapter(PlayerDetails playerDetails){this.playerDetails = playerDetails;}@Overridepublic void run() {System.out.printf("Run %s. Run!%n", playerDetails.getName());}public PlayerDetails getPlayerDetails() {return playerDetails;}
}

DefencePlayerAdapter.java

package com.blogspot.toomuchcoding.adapter;import com.blogspot.toomuchcoding.model.DJ;
import com.blogspot.toomuchcoding.model.DefensivePlayer;
import com.blogspot.toomuchcoding.model.JavaDeveloper;
import com.blogspot.toomuchcoding.model.PlayerDetails;/*** User: mgrzejszczak* Date: 09.06.13* Time: 15:42*/
public class DefencePlayerAdapter extends CommonPlayerAdapter implements DefensivePlayer, DJ, JavaDeveloper {public DefencePlayerAdapter(PlayerDetails playerDetails){super(playerDetails);}@Overridepublic void defend(){System.out.printf("Defence! %s. Defence!%n", getPlayerDetails().getName());}@Overridepublic void playSomeMusic() {System.out.println("Oops I did it again...!");}@Overridepublic void doSomeSeriousCoding() {System.out.println("System.out.println(\"Hello world\");");}
}

OffensivePlayerAdapter.java

package com.blogspot.toomuchcoding.adapter;import com.blogspot.toomuchcoding.model.OffensivePlayer;
import com.blogspot.toomuchcoding.model.PlayerDetails;/*** User: mgrzejszczak* Date: 09.06.13* Time: 15:42*/
public class OffensivePlayerAdapter extends CommonPlayerAdapter implements OffensivePlayer {public OffensivePlayerAdapter(PlayerDetails playerDetails){super(playerDetails);}@Overridepublic void shoot(){System.out.printf("%s Shooooot!.%n", getPlayerDetails().getName());}
}

好的,现在让我们转到更有趣的部分。 让我们假设我们有一个非常简单的玩家工厂:

PlayerFactoryImpl.java

package com.blogspot.toomuchcoding.factory;import com.blogspot.toomuchcoding.adapter.CommonPlayerAdapter;
import com.blogspot.toomuchcoding.adapter.DefencePlayerAdapter;
import com.blogspot.toomuchcoding.adapter.OffensivePlayerAdapter;
import com.blogspot.toomuchcoding.model.Player;
import com.blogspot.toomuchcoding.model.PlayerDetails;
import com.blogspot.toomuchcoding.model.PositionType;/*** User: mgrzejszczak* Date: 09.06.13* Time: 15:53*/public class PlayerFactoryImpl implements PlayerFactory {@Overridepublic Player createPlayer(PositionType positionType) {PlayerDetails player = createCommonPlayer(positionType);switch (positionType){case ATT:return new OffensivePlayerAdapter(player);case MID:return new OffensivePlayerAdapter(player);case DEF:return new DefencePlayerAdapter(player);case GK:return new DefencePlayerAdapter(player);default:return new CommonPlayerAdapter(player);}}private PlayerDetails createCommonPlayer(PositionType positionType){PlayerDetails playerDetails = new PlayerDetails();playerDetails.setPosition(positionType);return playerDetails;}
}

好的,我们有一家制造Player的工厂。 让我们看一下使用工厂的服务:

PlayerServiceImpl.java

package com.blogspot.toomuchcoding.service;import com.blogspot.toomuchcoding.factory.PlayerFactory;
import com.blogspot.toomuchcoding.model.*;/*** User: mgrzejszczak* Date: 08.06.13* Time: 19:02*/
public class PlayerServiceImpl implements PlayerService {private PlayerFactory playerFactory;@Overridepublic Player playAGameWithAPlayerOfPosition(PositionType positionType) {Player player = playerFactory.createPlayer(positionType);player.run();performAdditionalActions(player);return player;}private void performAdditionalActions(Player player) {if(player instanceof OffensivePlayer){OffensivePlayer offensivePlayer = (OffensivePlayer) player;performAdditionalActionsForTheOffensivePlayer(offensivePlayer);}else if(player instanceof DefensivePlayer){DefensivePlayer defensivePlayer = (DefensivePlayer) player;performAdditionalActionsForTheDefensivePlayer(defensivePlayer);}}private void performAdditionalActionsForTheOffensivePlayer(OffensivePlayer offensivePlayer){offensivePlayer.shoot();}private void performAdditionalActionsForTheDefensivePlayer(DefensivePlayer defensivePlayer){defensivePlayer.defend();try{DJ dj = (DJ)defensivePlayer;dj.playSomeMusic();JavaDeveloper javaDeveloper = (JavaDeveloper)defensivePlayer;javaDeveloper.doSomeSeriousCoding();}catch(ClassCastException exception){System.err.println("Sorry, I can't do more than just play football...");}}public PlayerFactory getPlayerFactory() {return playerFactory;}public void setPlayerFactory(PlayerFactory playerFactory) {this.playerFactory = playerFactory;}
}

让我们承认吧……这段代码很糟糕。 在内部,当您查看它时(无论它是否使用 operator 实例 ),您都认为它是邪恶的。 正如您在代码中看到的那样,我们正在进行一些类强制转换……我们到底如何进行测试? 在大多数测试框架中,您无法对模拟进行此类类转换,因为它们是使用CGLIB库构建的,并且可能会抛出一些ClassCastExceptions。 您仍然无法返回模拟和真实的实现(假设这些模拟和构建不会在构建过程中执行任何丑陋的工作),并且它实际上可以工作,但仍然如此–这是错误的代码

自带的Mockito给救援(虽然你不应该过度使用此功能-事实上,如果你需要使用它,请考虑重构它)与其extraInterfaces特点:

extraInterfaces

MockSettings extraInterfaces (java.lang.Class <?>…接口)

指定模拟应实现的额外接口。 对于遗留代码或某些极端情况可能很有用。 有关背景信息,请参见此处的问题51。此神秘功能应经常使用。 被测对象应该确切知道其协作者和依赖性。 如果您碰巧经常使用它,请确保您确实在生成简单,干净且可读的代码。

例子:

Foo foo = mock(Foo.class, withSettings().extraInterfaces(Bar.class, Baz.class));//now, the mock implements extra interfaces, so following casting is possible:Bar bar = (Bar) foo;Baz baz = (Baz) foo;

参数:

interfaces –应该实现的额外接口。

返回值:设置实例,以便您可以流畅地指定其他设置
现在让我们看一下测试:

PlayerServiceImplTest.java

package com.blogspot.toomuchcoding.service;import com.blogspot.toomuchcoding.factory.PlayerFactory;
import com.blogspot.toomuchcoding.model.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.*;/*** User: mgrzejszczak* Date: 08.06.13* Time: 19:26*/
@RunWith(MockitoJUnitRunner.class)
public class PlayerServiceImplTest {@MockPlayerFactory playerFactory;@InjectMocksPlayerServiceImpl objectUnderTest;@Mock(extraInterfaces = {DJ.class, JavaDeveloper.class})DefensivePlayer defensivePlayerWithDjAndJavaDevSkills;@MockDefensivePlayer defensivePlayer;@MockOffensivePlayer offensivePlayer;@MockPlayer commonPlayer;@Testpublic void shouldReturnOffensivePlayerThatRan() throws Exception {//givengiven(playerFactory.createPlayer(PositionType.ATT)).willReturn(offensivePlayer);//whenPlayer createdPlayer = objectUnderTest.playAGameWithAPlayerOfPosition(PositionType.ATT);//thenassertThat(createdPlayer == offensivePlayer, is(true));verify(offensivePlayer).run();}@Testpublic void shouldReturnDefensivePlayerButHeWontBeADjNorAJavaDev() throws Exception {//givengiven(playerFactory.createPlayer(PositionType.GK)).willReturn(defensivePlayer);//whenPlayer createdPlayer = objectUnderTest.playAGameWithAPlayerOfPosition(PositionType.GK);//thenassertThat(createdPlayer == defensivePlayer, is(true));verify(defensivePlayer).run();verify(defensivePlayer).defend();verifyNoMoreInteractions(defensivePlayer);}@Testpublic void shouldReturnDefensivePlayerBeingADjAndAJavaDev() throws Exception {//givengiven(playerFactory.createPlayer(PositionType.GK)).willReturn(defensivePlayerWithDjAndJavaDevSkills);doAnswer(new Answer<Object>() {@Overridepublic Object answer(InvocationOnMock invocationOnMock) throws Throwable {System.out.println("Hit me baby one more time!");return null;}}).when(((DJ) defensivePlayerWithDjAndJavaDevSkills)).playSomeMusic();doAnswer(new Answer<Object>() {@Overridepublic Object answer(InvocationOnMock invocationOnMock) throws Throwable {System.out.println("public static void main(String... args){\n}");return null;}}).when(((JavaDeveloper) defensivePlayerWithDjAndJavaDevSkills)).doSomeSeriousCoding();//whenPlayer createdPlayer = objectUnderTest.playAGameWithAPlayerOfPosition(PositionType.GK);//thenassertThat(createdPlayer == defensivePlayerWithDjAndJavaDevSkills, is(true));verify(defensivePlayerWithDjAndJavaDevSkills).run();verify(defensivePlayerWithDjAndJavaDevSkills).defend();verify((DJ) defensivePlayerWithDjAndJavaDevSkills).playSomeMusic();verify((JavaDeveloper) defensivePlayerWithDjAndJavaDevSkills).doSomeSeriousCoding();}@Testpublic void shouldReturnDefensivePlayerBeingADjAndAJavaDevByUsingWithSettings() throws Exception {//givenDefensivePlayer defensivePlayerWithDjAndJavaDevSkills = mock(DefensivePlayer.class, withSettings().extraInterfaces(DJ.class, JavaDeveloper.class));given(playerFactory.createPlayer(PositionType.GK)).willReturn(defensivePlayerWithDjAndJavaDevSkills);doAnswer(new Answer<Object>() {@Overridepublic Object answer(InvocationOnMock invocationOnMock) throws Throwable {System.out.println("Hit me baby one more time!");return null;}}).when(((DJ) defensivePlayerWithDjAndJavaDevSkills)).playSomeMusic();doAnswer(new Answer<Object>() {@Overridepublic Object answer(InvocationOnMock invocationOnMock) throws Throwable {System.out.println("public static void main(String... args){\n}");return null;}}).when(((JavaDeveloper) defensivePlayerWithDjAndJavaDevSkills)).doSomeSeriousCoding();//whenPlayer createdPlayer = objectUnderTest.playAGameWithAPlayerOfPosition(PositionType.GK);//thenassertThat(createdPlayer == defensivePlayerWithDjAndJavaDevSkills, is(true));verify(defensivePlayerWithDjAndJavaDevSkills).run();verify(defensivePlayerWithDjAndJavaDevSkills).defend();verify((DJ) defensivePlayerWithDjAndJavaDevSkills).playSomeMusic();verify((JavaDeveloper) defensivePlayerWithDjAndJavaDevSkills).doSomeSeriousCoding();}@Testpublic void shouldReturnCommonPlayer() throws Exception {//givengiven(playerFactory.createPlayer(null)).willReturn(commonPlayer);//whenPlayer createdPlayer = objectUnderTest.playAGameWithAPlayerOfPosition(null);//thenassertThat(createdPlayer, is(commonPlayer));}
}

这里有很多测试,所以让我们看一下最有趣的测试。 但是在开始之前,我们先:提供@RunWith(MockitoJUnitRunner.class)批注,它使我们能够使用Mockito批注,例如@Mock@InjectMocks

说到哪个@Mock注释会创建一个Mock,而@InjectMocks则通过构造函数或setter注入所有模拟(这太棒了吗?)。

对于防御性玩家,我们使用注解extraInterfaces的extra元素,该元素为给定的Mock提供其他接口。 您还可以编写(可以在shouldReturnDefensivePlayerBeingADjAndAJavaDevByUsingWithSettings测试中找到的内容 ):

DefensivePlayer defensivePlayerWithDjAndJavaDevSkills = mock(DefensivePlayer.class, withSettings().extraInterfaces(DJ.class, JavaDeveloper.class));

让我们仔细看看为与DefensivePlayer相关的功能和被测函数的转换部分编写的测试:

@Testpublic void shouldReturnDefensivePlayerBeingADjAndAJavaDev() throws Exception {//givengiven(playerFactory.createPlayer(PositionType.GK)).willReturn(defensivePlayerWithDjAndJavaDevSkills);doAnswer(new Answer<Object>() {@Overridepublic Object answer(InvocationOnMock invocationOnMock) throws Throwable {System.out.println("Hit me baby one more time!");return null;}}).when(((DJ) defensivePlayerWithDjAndJavaDevSkills)).playSomeMusic();doAnswer(new Answer<Object>() {@Overridepublic Object answer(InvocationOnMock invocationOnMock) throws Throwable {System.out.println("public static void main(String... args){\n}");return null;}}).when(((JavaDeveloper) defensivePlayerWithDjAndJavaDevSkills)).doSomeSeriousCoding();//whenPlayer createdPlayer = objectUnderTest.playAGameWithAPlayerOfPosition(PositionType.GK);//thenassertThat(createdPlayer == defensivePlayerWithDjAndJavaDevSkills, is(true));verify(defensivePlayerWithDjAndJavaDevSkills).run();verify(defensivePlayerWithDjAndJavaDevSkills).defend();verify((DJ) defensivePlayerWithDjAndJavaDevSkills).playSomeMusic();verify((JavaDeveloper) defensivePlayerWithDjAndJavaDevSkills).doSomeSeriousCoding();}

我们正在使用BDDMockito静态方法,如给定(...)。willReturn(...)。willAnswer(...)等。然后,将空方法与自定义Anwsers结合使用。 在下一行中,您可以看到,为了存根另一个接口的方法,必须将模拟转换为给定的接口。 这与验证阶段有关,在该阶段,我不检查是否已执行方法,您必须将模拟转换为给定的接口。

您可以通过从工厂返回一个实际的实现来改进测试,或者如果创建一个繁琐的操作,则可以返回这种实现的模拟。 我想在这里展示的是如何在Mockito中使用额外的接口(也许我的用例不是最好的用例)。 无论如何,测试中提出的实现都是不好的,所以我们应该考虑重构它的方法……

一种想法可能是,假设在Service中完成的附加逻辑是对象创建的一部分,将代码原样移至工厂:

PlayFactoryImplWithFieldSettingLogic.java

package com.blogspot.toomuchcoding.factory;import com.blogspot.toomuchcoding.adapter.CommonPlayerAdapter;
import com.blogspot.toomuchcoding.adapter.DefencePlayerAdapter;
import com.blogspot.toomuchcoding.adapter.OffensivePlayerAdapter;
import com.blogspot.toomuchcoding.model.*;/*** User: mgrzejszczak* Date: 09.06.13* Time: 15:53*/public class PlayerFactoryImplWithFieldSettingLogic implements PlayerFactory {@Overridepublic Player createPlayer(PositionType positionType) {PlayerDetails player = createCommonPlayer(positionType);switch (positionType){case ATT:return createOffensivePlayer(player);case MID:return createOffensivePlayer(player);case DEF:return createDefensivePlayer(player);case GK:return createDefensivePlayer(player);default:return new CommonPlayerAdapter(player);}}private Player createDefensivePlayer(PlayerDetails player) {DefencePlayerAdapter defencePlayerAdapter = new DefencePlayerAdapter(player);defencePlayerAdapter.defend();defencePlayerAdapter.playSomeMusic();defencePlayerAdapter.doSomeSeriousCoding();return defencePlayerAdapter;}private OffensivePlayer createOffensivePlayer(PlayerDetails player) {OffensivePlayer offensivePlayer = new OffensivePlayerAdapter(player);offensivePlayer.shoot();return offensivePlayer;}private PlayerDetails createCommonPlayer(PositionType positionType){PlayerDetails playerDetails = new PlayerDetails();playerDetails.setPosition(positionType);return playerDetails;}
}

这样就没有强制转换代码是真正干净的。 现在,PlayerService如下所示:

PlayerServiceImplWIthoutUnnecessaryLogic.java

package com.blogspot.toomuchcoding.service;import com.blogspot.toomuchcoding.factory.PlayerFactory;
import com.blogspot.toomuchcoding.model.*;/*** User: mgrzejszczak* Date: 08.06.13* Time: 19:02*/
public class PlayerServiceImplWithoutUnnecessaryLogic implements PlayerService {private PlayerFactory playerFactory;/*** What's the point in having this method then?* @param positionType* @return*/@Overridepublic Player playAGameWithAPlayerOfPosition(PositionType positionType) {return playerFactory.createPlayer(positionType);}public PlayerFactory getPlayerFactory() {return playerFactory;}public void setPlayerFactory(PlayerFactory playerFactory) {this.playerFactory = playerFactory;}
}

随之而来的问题是,您的代码库中是否甚至需要这种方法……

总结一下,我希望我能展示如何:

  • 使用MockitoJUnitRunner以干净的方式注入模拟
  • 使用注释或静态方法添加可以被您的模拟使用的额外接口
  • 使用BDDMockito执行方法存根
  • 带有自定义答案的存根无效方法
  • 附加接口的存根和验证方法
  • 重构使用类强制转换的代码

这些源可在TooMuchCoding Bitbucket存储库和TooMuchCoding Github存储库中找到。

参考: Mockito –来自我们的JCG合作伙伴 Marcin Grzejszczak(位于Blog上)的 具有注释和静态方法的Extra Interfaces, 用于编码瘾君子博客。

翻译自: https://www.javacodegeeks.com/2013/06/mockito-extra-interfaces-with-annotations-and-static-methods.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

怎么把原来的墙拆掉_家装拆除不是简单的砸砸墙,它也是有技术的

装修拆除中有很多人认为&#xff0c;拆除施工没有什么技术含量&#xff0c;感觉就像小品演的那样&#xff0c;挥挥大锤砸砸墙就可以了。所以有的人图便宜就从马路上随便找的工人来砸墙&#xff0c;他们不管是不是承重墙&#xff0c;只要业主要求他们就敢咋&#xff0c;后果真有…

20180209-os模块

下面将学习关于os模块的相关操作 项目练习的目录结构如下&#xff1a;所有的操作都是基于os_exercise.py模块 1.获取当前的Python脚本的工作目录路径 os.getcwd() # 1.获取当前目录 dir os.getcwd() print(获取当前python脚本工作目录:,dir) # 输出 # 获取当前python脚本工作目…

UOJ #188. 【UR #13】Sanrd

Description 给定 \(\sum_{il}^r f[i]\)\(f[i]\) 把 \(i\) 的每一个质因子都从小到大排列成一个序列(\(p_i^{c_i}\)要出现 \(c_i\) 次)后 , 第二大的质因子.题面 Solution 符合 \(Min25\) 筛的处理顺序. 递归处理每个质因子作为次大值时的贡献,和不作为次大值时贡献的方案数 , …

关于IE6.7.8.FF兼容的问题

所有浏览器 通用 height: 100px; IE6 专用 _height: 100px;IE6 专用 *height: 100px; IE7 专用 * height: 100px; IE7、FF 共用 height: 100px !important; 一、CSS 兼容 以下两种方法几乎能解决现今所有兼容. 1, !important (不是很推荐&#xff0c;用下面的一种感觉最安…

冯珊珊_模拟器企业衡泰信签约冯珊珊,推动高尔夫运动下沉

9月21日&#xff0c;著名高尔夫模拟器企业衡泰信宣布签约中国高尔夫球员冯珊珊&#xff0c;双方正式达成全面战略合作&#xff0c;旨在共同推动室内高尔夫运动的普及与推广&#xff0c;让更多人参与并喜爱上这项运动&#xff0c;推动全民健身目标&#xff0c;借助互联网、智慧场…

MOXy是GlassFish 4中新的默认JSON绑定提供程序

GlassFish 4现在可以提供完整的Java EE 7&#xff08;JSR-342&#xff09;平台。 EclipseLink为该发行版做出了一些重大贡献。 首先是提供JPA 2.1&#xff08;JSR-338&#xff09;实现。 我将在本文中介绍的第二个内容是EclipseLink MOXy&#xff0c;它现在是JAX-RS应用程序的默…

假期第四周周总结

第四周&#xff1a; 本周做了什么&#xff1a;由于第一次科三没过&#xff0c;只能再约一次&#xff0c;两天在练科三&#xff0c;其他时间都在安装oracle&#xff0c;虚拟机&#xff0c;并配置环境&#xff0c;学习oracle数据库&#xff0c;并改进河北创新科技平台系统 收获是…

通过form实现enter事件

结构 <form action‘#’> <input typesearch /> <button>搜索</button> </form> 在这种情况下即使给button加上事件&#xff0c;按enter键也会执行点击事件中的代码&#xff08;pc-移动web皆可以&#xff09;。&#xff08;action需为javascript…

CSS3之background的调整和增加的属性

对于background做了一些修改&#xff0c;最明显的一个就是采用设置多背景&#xff0c;不但添加了4个新属性&#xff0c;并且还对目前的属性进行了调整增强。 1、多个背景图片 在css3里面&#xff0c;你可以再一个标签元素里应用多个背景图片。代码类似与css2.0版本的写法&…

html 天气特效,用CSS制作天气特效动画,源码分享

效果图今天给大家带来的是CSS3动画天气图标代码&#xff0c;简单实用好看&#xff01;CSS源码&#xff1a;html { box-sizing: border-box; }html *,html *:before,html *:after { box-sizing: inherit; }body {max-width: 42em;padding: 2em;margin: 0 auto;color: #161616;fo…

做折线图坐标轴数字_Excel折线图表的另类表达制作?牛闪君使用了双线表达法来完成...

牛闪闪办公第846个原创技巧Zloffice社群的小伙伴还是很爱学习的&#xff0c;这不&#xff0c;有一位小伙伴看到“特殊”图表表达&#xff0c;想知道是怎么做出来的。这种学习的思路非常好&#xff0c;看到好的表达就想学习&#xff0c;这是非常好的收集习惯&#xff0c;能够积累…

Spring MVC控制器的单元测试:“普通”控制器

本教程的第一部分描述了如何配置使用Spring MVC Test框架的单元测试 。 现在是时候动手做&#xff0c;学习如何为“常规”控制器编写单元测试了。 显而易见的下一个问题是&#xff1a; 什么是普通控制器&#xff1f; 好吧&#xff0c;一个普通的控制器&#xff08;在此博客文…

回溯法

一、概念&#xff1a;回溯法也是一种枚举&#xff0c;但是回溯法将枚举(生成&#xff09;和检查有机结合起来&#xff0c;从而减少了不必要的枚举。。 二、经典八皇后问题。 #include<iostream> #include<cmath> using namespace std;int vis[100]; int store[100]…

【Spring】入门HelloWorld

参考&#xff1a;https://www.yiibai.com/spring/spring-tutorial-for-beginners.html 一、创建项目 1.利用IntelliJ创建Maven项目2.配置pom.xml,引入Spring <?xml version"1.0" encoding"UTF-8"?> 4.0.0 <groupId>com.jh</groupId> &…

html属性可以用来定义内联样式,18年6月考试《网页设计与制作》期末大作业.doc...

...(单选题) 1: 以下HTML代码&#xff0c;判断正确的是( )。 A: 错了B: “button”双引号错了(应为单引号)C: 第2、3行应加入…….D: 没有错误正确答案:(单选题) 2: 数据库的基本操作是( )。A: 增&#xff0c;删&#xff0c;改&#xff0c;查B: 增&#xff0c;删&#xff0c;加…

DIV CSS初学者需重视的10个简单问题与技巧

DIVCSS初学者往往感觉自己遇到很多莫明其妙的问题&#xff0c;其实只是一些小细节没有引起重视&#xff0c;下面罗列了10个问题与技巧&#xff0c;温故而知新。 一、检查HTML元素是否有拼写错误、是否忘记结束标记即使是老手也经常会弄错div的嵌套关系。可以用dreamweaver的验…

Spring MVC:表单处理卷。 5 –选择,选项,选项标签

下拉列表是Web表单中最常见的元素之一。 在HTML中&#xff0c;可以使用适当的标签创建此类控件&#xff1a; <form&#xff1a;select> –下拉列表的父标签和<form&#xff1a;option> – <form&#xff1a;select>标签的子标签。 Spring MVC标签库为下拉列表…

06.linux平台下运行go文件

1.获取linux位数 getconf LONG_BIT 2.下载地址&#xff1a; https://studygolang.com/dl 3.解压安装包 sudo tar -xzf go1.9.2.linux-amd64.tar.gz -C /usr/local 4.设置环境变量 sudo vi /etc/profile export GOROOT/usr/local/go export GOBIN$GOROOT/bin export GOPATH/h…

python3读取ini文件_python3配置文件ini读取方法

1.最常用的Plain text形式的配置文件 1.1首选 .init 文件 标准库 configparser 1.2次选 csv文件 与 Unix/Linux 下常用的 xx xxx形式的配置文件 分别是标准库csv 与 shlex 2.最常用的二进制级配置文件 2.1持久化数据首选shelve 标准库 shelve 2.2shelve的对于一些项目我们需要…

Python的看门狗实现自动化实时对服务器、Windows或Linux文件夹的实时监控

众所周知&#xff0c;在运维过程中&#xff0c;实时获取目标文件夹至关重要&#xff0c;Python的watchdog是用程序来监视文件系统事件Python库&#xff0c;所以用该库可以实现对文件夹的实时监控&#xff0c;filenotify.py代码如下&#xff1a; # -*- coding: utf-8 -*- #!/usr…