Spring Boot ã§ãã°ã¤ã³ç»é¢ + ä¸è¦§ç»é¢ + ç»é²ç»é¢ã® Webã¢ããªã±ã¼ã·ã§ã³ãä½ã ( ãã®ï¼ï¼ )( æ¤ç´¢/ä¸è¦§ç»é¢ ( MyBatis-Springç ) ä½æï¼ )
æ¦è¦
Spring Boot ã§ãã°ã¤ã³ç»é¢ + ä¸è¦§ç»é¢ + ç»é²ç»é¢ã® Webã¢ããªã±ã¼ã·ã§ã³ãä½ã ( ãã®ï¼ï¼ )( ç»é²ç»é¢ä½æï¼ ) ã®ç¶ãã§ãã
-
ä»åã®æé ã§ç¢ºèªã§ããã®ã¯ä»¥ä¸ã®å 容ã§ãã
- æ¤ç´¢/ä¸è¦§ç»é¢ ( MyBatis-Springç ) ã®ãã¹ãã¯ã©ã¹ãæ¸ãã¾ãã
-
ä»åã¯æéããããã¾ããããã¹ãã¯ã©ã¹ãååããç¨åº¦æ¸ããããããªã«æéã¯ããããªãã ããã¨æã£ã¦ããã®ã§ããããããçç±ãæå¾ã«ã¾ã¨ãã¦ã¿ã¾ãã
ã½ããã¦ã§ã¢ä¸è¦§
åèã«ãããµã¤ã
è¿è¤åéªã®ããã°ã©ãã³ã°å·¥æ¿æ¥èª - MySQLã®æåã³ã¼ãé¢é£ã®è¨å®ã調ã¹ãæ¹æ³
http://blog.kondoyoshiyuki.com/2013/01/11/how2know-mysql-character-code/MySQL CSVãã¡ã¤ã«å ¥åºå
http://sasuke.main.jp/sqlcsv.htmlFight the Future - DbUnitã§èªã¿è¾¼ããã¡ã¤ã«ã®å¤ã«nullãè¨å®ãã
http://jyukutyo.hatenablog.com/entry/20080821/1219294435AssertFalse.java - Spring JIRA
https://jira.spring.io/secure/attachment/13763/AssertFalse.java- ãã¹ãã¯ã©ã¹ã§ãã¹ãã¯ã©ã¹ã使ç¨ããå ´åã«
@RunWith(SpringJUnit4ClassRunner.class)
ãã©ãã«ä»å ããã°ããã®ãåãããªãã£ãã®ã§ããã®æã«åç §ãã¾ããã - ãã®ã½ã¼ã¹ã§ã¯
@RunWith(Enclosed.class)
ã使ç¨ããã¦ãã¾ãããä»å ããå¿ è¦ã¯ããã¾ãã ( å¾è¿°åç § )ã
- ãã¹ãã¯ã©ã¹ã§ãã¹ãã¯ã©ã¹ã使ç¨ããå ´åã«
snakeyaml
https://code.google.com/p/snakeyaml/ã³ã³ãã¥ã¼ã¿ã¯ã¯ã¬ã¿ - Spring MVC 3.2ã®Spring MVC Testã触ã£ã
http://kuwalab.hatenablog.jp/entry/20130402/p1- ååã«å¼ãç¶ãåèã«ãã¾ããã
ãããããã¹ãã¼ã - Gradleã§Enclosedãã¹ãã2åå®è¡ããããã¨ã®å¯¾ç
http://d.hatena.ne.jp/shuji_w6e/20120808/1344386399- ãã¹ãã¯ã©ã¹ããã¹ãã¯ã©ã¹ã§æ§é åããããã¹ããï¼åå®è¡ãããããã«ãªã£ãã®ã§ã対çæ¹æ³ãåèã«ãã¾ããã
- ãã¹ãã¯ã©ã¹ã«ãã¦ã
@RunWith(Enclosed.class)
ãä»ããå¿ è¦ã¯ããã¾ããã§ããã
Spring Framework Reference Documentation - 8. Spring Expression Language (SpEL)
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.htmlpage.number
ã¨è¨è¿°ãã¦page.getNumber()
ã®æ»ãå¤ãåå¾ããæ¹æ³ã調ã¹ãæã«åç §ãã¾ããã- ä»åæ°è¦ã«ä½æãã¦ãã CustomModelResultMatchers ã¯ã©ã¹ã«åæ ãã¦ãã¾ãã
mysql querying a utf charset table for c returns ç
http://stackoverflow.com/questions/10231490/mysql-querying-a-utf-charset-table-for-c-returns-%C3%A7Mysqlãã¼ãã«ã®ç §åé åºãå¤æ´ãã
http://joppot.info/2014/02/03/601
æé
æ¤è¨¼åã«ãã¼ãã«ã® charset ã確èªããã latin1 ã§ããããã
world ãã¼ã¿ãã¼ã¹ã® DEFAULT CHARSET ã¨ãcountry ãã¼ãã«ã® DEFAULT CHARSET ã調ã¹ãã¨ããããã¼ã¿ãã¼ã¹ã® DEFAULT CHARSET 㯠utf8 ãªã®ã«ããªãã country ãã¼ãã«ã® DEFAULT CHARSET 㯠latin1 ã§ããã
mysql> show create database world; +----------+----------------------------------------------------------------+ | Database | Create Database | +----------+----------------------------------------------------------------+ | world | CREATE DATABASE `world` /*!40100 DEFAULT CHARACTER SET utf8 */ | +----------+----------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> show create table country; | country | CREATE TABLE `country` ( `Code` char(3) NOT NULL DEFAULT '', `Name` char(52) NOT NULL DEFAULT '', `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia', `Region` char(26) NOT NULL DEFAULT '', `SurfaceArea` float(10,2) NOT NULL DEFAULT '0.00', `IndepYear` smallint(6) DEFAULT NULL, `Population` int(11) NOT NULL DEFAULT '0', `LifeExpectancy` float(3,1) DEFAULT NULL, `GNP` float(10,2) DEFAULT NULL, `GNPOld` float(10,2) DEFAULT NULL, `LocalName` char(45) NOT NULL DEFAULT '', `GovernmentForm` char(45) NOT NULL DEFAULT '', `HeadOfState` char(60) DEFAULT NULL, `Capital` int(11) DEFAULT NULL, `Code2` char(2) NOT NULL DEFAULT '', PRIMARY KEY (`Code`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
ãã¼ãã«ã®ã«ã©ã ã®è¨å®ã確èªãã¦ã¿ããããã£ã±ã latin1 ã§ãããä»ã©ã latin1 ã®è¨å®ãæ®ãã¦ããå¿ è¦ãªãã¦ã©ãã«ããªãã¨æãã®ã§ããããã
ãã®ã¾ã¾ã§ã¯ utf8 ã®ãã¼ã¿ãå ¥ããããªãã®ã§ããã¼ãã«ã¨ã«ã©ã ã® CHARSET ã utf8 ã«å¤æ´ãã¾ãã
mysql> alter table country convert to character set utf8; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table country; | country | CREATE TABLE `country` ( `Code` char(3) NOT NULL DEFAULT '', `Name` char(52) NOT NULL DEFAULT '', `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia', `Region` char(26) NOT NULL DEFAULT '', `SurfaceArea` float(10,2) NOT NULL DEFAULT '0.00', `IndepYear` smallint(6) DEFAULT NULL, `Population` int(11) NOT NULL DEFAULT '0', `LifeExpectancy` float(3,1) DEFAULT NULL, `GNP` float(10,2) DEFAULT NULL, `GNPOld` float(10,2) DEFAULT NULL, `LocalName` char(45) NOT NULL DEFAULT '', `GovernmentForm` char(45) NOT NULL DEFAULT '', `HeadOfState` char(60) DEFAULT NULL, `Capital` int(11) DEFAULT NULL, `Code2` char(2) NOT NULL DEFAULT '', PRIMARY KEY (`Code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 | mysql> alter table city convert to character set utf8; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table countrylanguage convert to character set utf8; Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0
ã«ã©ã ã® CHARSET ã utf8 ã«å¤æ´ããã¾ããã
MySQL ã®æåã³ã¼ãé¢é£ã®è¨å®ã cp932 ã§è¨å®ããã¦ãããã®ãããã¾ãããDbUnit ã§æ¥ç¶ã㦠utf8 ã®ãã¼ã¿ãæå ¥ããã®ã§ utf8 ã«å¤æ´ãã¾ãã
mysql> show variables like 'char%'; +--------------------------+---------------------------------------------------- -----+ | Variable_name | Value | +--------------------------+---------------------------------------------------- -----+ | character_set_client | cp932 | | character_set_connection | cp932 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | cp932 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | C:\Program Files\MySQL\MySQL Server 5.6\share\chars ets\ | +--------------------------+---------------------------------------------------- -----+ 8 rows in set (0.00 sec) mysql> set character_set_client = utf8; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_connection = utf8; Query OK, 0 rows affected (0.00 sec) mysql> set character_set_results = utf8; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'char%'; +--------------------------+---------------------------------------------------------+ | Variable_name | Value | +--------------------------+---------------------------------------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | C:\Program Files\MySQL\MySQL Server 5.6\share\charsets\ | +--------------------------+---------------------------------------------------------+ 8 rows in set (0.00 sec)
ãã¹ãã¯ã©ã¹ä½æåã®æºå
IntelliJ IDEA ä¸ã§ 1.0.x-testcountrylist ãã©ã³ããä½æãã¾ãã
ååãç»é²ç»é¢ ( å ¥åâ確èªâå®äº ) ã®ãã¹ãã¯ã©ã¹ãæ¸ãã¾ããããJUnit ãå ¨ç¶ç解ãã¦ããªãã¦ããªãè¦å´ããã®ã§ã以ä¸ã®æ¸ç±ãè²·ã£ã¦ãã¦èªã¿ã¾ãããï¼å¹´åãããã«çºè¡ãããæ¸ç±ã§ãããJUnit4 ã®ãã¨ãååå¿ è¦ãªãã¨ãæ¸ããã¦ãããåãããããã¦ããããããã«ãªãã¾ããã
JUnitå®è·µå ¥é ~ä½ç³»çã«å¦ã¶ã¦ããããã¹ãã®ææ³ (WEB+DB PRESS plus)
- ä½è : 渡辺修å¸
- åºç社/ã¡ã¼ã«ã¼: æè¡è©è«ç¤¾
- çºå£²æ¥: 2012/11/21
- ã¡ãã£ã¢: åè¡æ¬ï¼ã½ããã«ãã¼ï¼
- è³¼å ¥: 14人 ã¯ãªãã¯: 273å
- ãã®ååãå«ãããã° (68件) ãè¦ã
ä»åã¯ä»¥ä¸ã®ç¹ã«æ³¨æãã¦ãã¹ãã¯ã©ã¹ãä½æãã¦ã¿ã¾ãã
- ï¼ãã¹ãï¼ã¡ã½ããã«ãã¾ãã
- ãã¹ãã¡ã½ããåãæ¥æ¬èªã«ãã¾ã ( ãJUnitå®è·µå ¥éãã«ãè¦ãã¨æ¸ããã¦ããã®ã§ä»åã¯ããã«å¾ã£ã¦ã¿ã¾ã ) ã
- ãã¹ãã¯ã©ã¹ã®ä¸ã«
public static class ãã¹ãã°ã«ã¼ãå { ... }
ã®å½¢å¼ã§ãã¹ãã¯ã©ã¹ãå®ç¾©ãããã¨ã§ããã¹ãã±ã¼ã¹ãã°ã«ã¼ãåã»æ§é åãã¾ãã - DbUnit ãå©ç¨ãã DB ã®åæåå¦çã¯æéããããã®ã§ãDBã使ç¨ãããã¹ãã¯ç¹å®ã®ãã¹ããããã¹ãã¯ã©ã¹ã®ã¿ã«ãããã以å¤ã®ãã¹ããããã¹ãã¯ã©ã¹ã§ã¯ DbUnit ãå©ç¨ããåæåå¦çãè¡ãããªãããã«ãã¾ãã
- Form ã¯ã©ã¹ã®åæå¤ãååã¯ã¯ã©ã¹ã®ä¸ã«ç´æ¥æ¸ãã¾ããããYAML ãã¡ã¤ã«ã«å®ç¾©ãã¦èªã¿è¾¼ãã§ã»ããããæ¹æ³ãããã®ã§ãããã試ãã¦ã¿ã¾ãã
Form ã¯ã©ã¹ã®ãã¹ããã¼ã¿ã YAML ãã¡ã¤ã«ã«å®ç¾©ãã¦èªã¿è¾¼ãããã«ãã¾ããSnakeYAML ã¨ããã©ã¤ãã©ãªã使ç¨ããã®ã§ãbuild.gradle ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
å¤æ´å¾ãGradle tasks View ã®ãRefresh Gradle projectsãã¢ã¤ã³ã³ãã¯ãªãã¯ãã¦ãå¤æ´ãã build.gradle ã®å 容ãåæ ãããã¨ãã㨠IntelliJ IDEA ã®ç»é¢å³ä¸ã«ä»¥ä¸ã®ç»åã®ã¡ãã»ã¼ã¸ã表示ããã¾ããã
ã¡ãã»ã¼ã¸ã®ä¸ã®ãOpen Repositories Listãã®ãªã³ã¯ãã¯ãªãã¯ãã¾ãã
ãSettingsããã¤ã¢ãã°ã表示ããã¾ããç»é¢å³å´ã®ãIndexed Maven Repositoriesãã®ä¸ã®
http://oss.http://oss.sonatype.org/content/groups/public/
ã®è¡ãé¸æå¾ããUpdateããã¿ã³ãã¯ãªãã¯ãã¾ãã- ã¢ãããã¼ãã¯çµæ§æéããããã¾ãã
ãUpdatedãæ¬ã«æ¥ä»ã表示ãããããOKããã¿ã³ãã¯ãªãã¯ãã¾ãã
å度 Gradle tasks View ã®ãRefresh Gradle projectsãã¢ã¤ã³ã³ãã¯ãªãã¯ãã¾ããä»åº¦ã¯ä½ã®ã¡ãã»ã¼ã¸ã表示ããã¾ããã§ãããExternal Libraries ã«ã snakeyaml ã® 1.16-SNAPSHOT ã表示ããã¦ãã¾ãã
src/test/resources ã®ä¸ã« ksbysample/webapp/basic/web ãã£ã¬ã¯ããªãä½æãã¾ããä½æå¾ãweb ãã£ã¬ã¯ããªã®ä¸ã« countryListForm_empty.yaml ãæ°è¦ä½æãããªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãããã£ã¬ã¯ããªæ§æã¯ä»¥ä¸ã®ç»åã®ããã«ãªãã¾ãã
åããã£ã¬ã¯ããªã®ä¸ã« countryListForm_code.yaml, countryListForm_name.yaml, countryListForm_continent.yaml, countryListForm_localName.yaml ã®ãã¡ã¤ã«ãæ°è¦ä½æãããªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
MockMvc ã® andExpect ã¡ã½ããå ã§ãModel ã«ã»ããããã¦ããå¤ã§ "page.number" ã 5 ã§ããããã§ãã¯ãããã®ããã« Thymeleaf ã®ãã³ãã¬ã¼ããã¡ã¤ã«ã«è¨è¿°ãã¦ããå½¢å¼ã§å¤ããã§ãã¯ãããã£ãã®ã§ãããæ¨æºã§ã¯ãã®ãããªã¯ã©ã¹ã»ã¡ã½ããããªãããã§ããã®ã§ããã§ãã¯ç¨ã®ã¯ã©ã¹ãä½æãã¾ããsrc/test/java/ksbysample/webapp/basic/test ã®ä¸ã« CustomModelResultMatchers.java ãæ°è¦ä½æãã¾ããä½æå¾ããªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
"page.number" ã¨è¨è¿°ããã Model ã«ã»ããããã¦ãã page ã¤ã³ã¹ã¿ã³ã¹ã® getNumber() ã®å¤ãåå¾ãããã¨ãããããã£ãã®ã§ãããæåã¯å ¨ãæ¹æ³ãåããã調ã¹ãã®ã«æéããããã¾ããã調ã¹ãæé ãã¡ã¢ãã¦ããã¾ãã
Thymeleaf ã®ãã³ãã¬ã¼ããã¡ã¤ã«ã§ã¯ page.number ã¨è¨è¿°ãã㨠page.getNumber() ã®å¤ãåå¾ãããã¨ãåºæ¥ã¦ããã®ã§ãã¾ã㯠Thymeleaf ã®ã½ã¼ã¹ãã¡ã¤ã« ãåç §ãã¦ã¿ã¾ããããã©ãã§å®ç¾ãã¦ããã®ãå ¨ãåããã¾ããã§ããã
Thymeleaf ã®ãã³ãã¬ã¼ããã¡ã¤ã«ã§ãã£ã¼ã«ããåå¨ããªããã° IntelliJ IDEA ã®ç»é¢ä¸ã« Exception ã¨ã½ã¼ã¹ãã¡ã¤ã«ã®è¡çªå·ã®ãã°ã表示ãããã ããã¨æããpagenation.html å ã®
page.number
ã¨æ¸ãã¦ããã¨ãããpage.numberx
ã«å¤æ´ãã¦å®è¡ããã¨ä»¥ä¸ã®ç»åã®ãã°ãåºåããã¾ãããThymeleaf ã§å¦çãã¦ãããã®ã¨æã£ã¦ããã®ã§ãããSpring Framework ã® SpelExpression ã¨ããã¯ã©ã¹ãå¼ã³åºãã¦ãã¾ããGoogle 㧠"SpelExpression" ã§æ¤ç´¢ãã㨠8. Spring Expression Language (SpEL) ã®ãã¼ã¸ãããããã¾ããããã®ä¸ã®ã8.3 Expression Evaluation using Springâs Expression Interfaceãã®ã½ã¼ã¹ãè¦ã¦è©¦ãã¦ã¿ãã¨ãããã¤ã³ã¹ã¿ã³ã¹åã® "page" 㨠ãã£ã¼ã«ãåã® "number" ãå¥éæå®ããã°å¤ãåå¾ãããã¨ã«æåãã¾ããã
"page.number" ã®å½¢å¼ã§åºæ¥ãããã«ãããã®ã§ãæ£è¦è¡¨ç¾ã§ã¤ã³ã¹ã¿ã³ã¹åã¨ãã£ã¼ã«ãåãåå²ããå¦çã追å ãã¾ããã
country ãã¼ãã«ã®ãã¹ããã¼ã¿ã®æºå
ãã¹ãã®æã« country ãã¼ãã«ã®ãã¼ã¿ã常ã«åãã«ãªããããã¹ããã¼ã¿ãæºåãã¾ãã
mysql ã³ãã³ãã§ä»¥ä¸ã®ã³ãã³ããå ¥åããcountry ãã¼ãã«ã®ãã¼ã¿ã country.csv ã¸åºåãã¾ãã
mysql> select * from country into outfile "c:/tmp/country.csv" fields terminated by ',' optionally enclosed by '"'; Query OK, 5 rows affected (0.00 sec) mysql>
åºåãã country.csv ãã¨ãã£ã¿ã§éããå é è¡ã«ã«ã©ã åã®è¡ã追å ãã\N â [null] ã¸ç½®æããå¾ ( NULL ã \N ã¨åºåããã¾ãããã®ã¾ã¾ã§ã¯ DbUnit ã§åãè¾¼ããªãã®ã§ç½®æãã¾ã )ãä¿åãã¾ããä¿åãã country.csv ã src/test/resources/testdata ã®ä¸ã«ã³ãã¼ï¼ãã¼ã¹ãã§é ç½®ãã¾ãããªã³ã¯å ã®å 容 ã®ãããªä¸èº«ã®ãã¡ã¤ã«ã«ãªãã¾ãã
src/test/resources/testdata ã®ä¸ã® table-ordering.txt ã ãªã³ã¯å ã®å 容 ã«å¤æ´ãã¾ãã
ç½®æãã [null] ã®æååã®å¤ã null ã§åãè¾¼ããããããããã«ãsrc/test/java/ksbysample/webapp/basic/test ã®ä¸ã® TestDataResource.java ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ãã
ãRun 'Tests in 'ksbysample...' with Coverageããé¸æãã¦ãã¹ããå®è¡ãããã¹ããå ¨ã¦æåãããã¨ã確èªãã¾ãã
ãã¹ãã¯æåããã®ã§ãããåãã¼ãã«ã®ãã¼ã¿ã確èªããã¨ãã country ãã¼ãã«ã®ãã¼ã¿ãï¼ä»¶ããæ»ã£ã¦ããããuser, user_role ãã¼ãã«ã®ãã¼ã¿ã¯å ¨ãå ã«æ»ã£ã¦ãã¾ããã§ãããåå ã調æ»ãã¾ãã
ã¨ã©ã¼ãåºã¦ããªãã®ã«ãã¼ã¿ãæ»ã£ã¦ããªãã®ã§ TestDataResource ã® after ã¡ã½ããã確èªããã¨ãããException ã catch ãã¦ä½ããã¦ãã¾ããã§ãããã¨ã©ã¼ãçºçãã¦ããã¯ããªã®ã§ã¨ã©ã¼å 容ãåºåãããããã«ãã¾ããsrc/test/java/ksbysample/webapp/basic/test ã®ä¸ã® TestDataResource.java ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ãã
ãRun 'Tests in 'ksbysample...' with Coverageããé¸æãã¦ãã¹ããå®è¡ããcountry ãã¼ãã«ã®ãã¼ã¿ãå ã«æ»ãã¾ãã
src/test/java/ksbysample/webapp/basic/test ã®ä¸ã® TestDataResource.java ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ãã
ãã¹ããå®è¡ãã㨠Too much output to process ã¨ããã¡ãã»ã¼ã¸ãåºåããã¦ãã¾ããã®ã§ãsrc/main/resources ã®ä¸ã® logback-develop.xml ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ãã
ãRun 'Tests in 'ksbysample...' with Coverageããé¸æãã¦ãã¹ããå®è¡ããã¨ããããã°ã«
java.lang.IllegalArgumentException: table.column=country.HeadOfState value is empty but must contain a value
ãåºåããã¦ãã¾ãããMySQL ã® country ãã¼ãã«ã®å®ç¾©ã確èªããã¨ãã country.HeadOfState 㯠Nullable = YES ã®è¨å®ã«ãªã£ã¦ãã¾ãã®ã§ç©ºã®ãã¼ã¿ã§ãåé¡ãªãããã§ãããDbUnit ã§ã¯ç©ºã®ãã¼ã¿ãå ¥ããããªãã¨ãããã¨ã§ããããï¼
"value is empty but must contain a value" 㧠Google ã§æ¤ç´¢ããã¨ããã以ä¸ã®ãã¼ã¸ãããããã¾ããã[NULL] ã¨æ¸ã㦠ReplacementDataSet ã§å¯¾å¿ããããæ¸ããã¦ãã¦ä¸æ¦ã¯ãã¼ãºããã¦ãã¾ããããã®å¾ã§ allowEmptyFields ã¨ããæ©è½ã追å ãã㦠2.5.1 ã§ä¿®æ£ãããã¨ãæ¸ãããã¾ãã
#363 Regression: cannot insert an empty string
http://sourceforge.net/p/dbunit/bugs/363/2.5.1 ãã¢ãããã¼ãããã¦ããã jCenter ã® org.dbunit:dbunit ã®ãã¼ã¸ ãã¿ãã¨ãããã¾ã 2.5.0 ã¾ã§ããã¢ãããã¼ãããã¦ãã¾ããã§ããã
ãã¹ããã¼ã¿ãå ¥ããæã« ReplacementDataSet ã¯ã©ã¹ã使ç¨ã㦠"[null]" ã¨ããæååãå®ç¾©ãã¦ããã° null ãã»ãããããããã«ããã®ã§ãããã¯ã¢ãããåå¾ããæã« null 㯠"[null]" ã¨ããæååã§åºåãã¦ããªã¹ãã¢æã« "[null]" ã¨ããæååãªãã° null ãã»ãããããã¨ãåºæ¥ãªãã試ãã¦ã¿ã¾ããsrc/test/java/ksbysample/webapp/basic/test ã®ä¸ã® TestDataResource.java ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ãã以ä¸ã®ç¹ãä¿®æ£ãã¦ãã¾ãã
- ãªã¹ãã¢å¦çã§ã¨ã©ã¼ãçºçããã¨ããã¯ã¢ãããã¡ã¤ã«ãåé¤ããå¦çãå¼ã³åºãããªããã¨ã«æ°ã¥ãã¾ããã®ã§ãä¿®æ£ãã¾ããã
- ãã¼ã¿ãå ã«æ»ããªãåå ã調æ»ãã¦ããæã«ããã¯ã¢ãããã¡ã¤ã«ãåé¤ããã¦ããªããã¨ã«ãæ°ã¥ãã¾ããã®ã§ãä¿®æ£ãã¾ããã
ãªã³ã¯å ã® SQL ãå®è¡ããuser, user_role ãã¼ãã«ã®ãã¼ã¿ãå ã«æ»ãã¾ãã
ãRun 'Tests in 'ksbysample...' with Coverageããé¸æãã¦ãã¹ããå®è¡ãã¾ããä»åº¦ã¯ user, user_role, country ãã¼ãã«å ¨ã¦ã§ãã¹ãåã®ãã¼ã¿ã«æ»ãã¾ããã
src/main/resources ã®ä¸ã® logback-develop.xml ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ã ( å ã«æ»ãã¾ã )ã
æ¤ç´¢/ä¸è¦§ç»é¢ ( MyBatis-Springç ) ã®ãã¹ãã¯ã©ã¹ã®ä½æ
src/test/java/ksbysample/webapp/basic/web ã®ä¸ã® CountryListControllerTest.java ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ãã
ãRun 'Tests in 'ksbysample...' with Coverageããé¸æãã¦ãã¹ããå®è¡ãã@Ignore ã¢ããã¼ã·ã§ã³ãä»å ãã¦ããªããã¹ããå ¨ã¦æåãããã¨ã確èªãã¾ãã
commitãGitHub 㸠Pushã1.0.x-testcountrylist -> 1.0.x 㸠Pull Requestã1.0.x ã§ãã¼ã¸ã1.0.x-testcountrylist ãã©ã³ããåé¤
commit ã®åã« build ã¿ã¹ã¯ãå®è¡ããBUILD SUCCESSFUL ã表示ããããã¨ã確èªãããã¨ãã¾ãããã以ä¸ã®ãã°ãåºåãã㦠BUILD FAILED ã«ãªãã¾ãããåå ã調æ»ãã¾ãã
MySQL Workbench 㧠"SELECT * FROM world.country where LocalName like '%oc%';" ãå®è¡ããã¨ï¼ä»¶ããããã¾ãããï¼ä»¶ã¯ "oc" ã§ã¯ãªã "oç" ã§ããã
bootRun ã¿ã¹ã¯ãå®è¡ã㦠Tomcat ãèµ·åããå¾ãæ¤ç´¢/ä¸è¦§ç»é¢ãã localname ã« "oc" ãå ¥åãã¦ãæ¤ç´¢ããã¿ã³ãã¯ãªãã¯ãã¾ãããã¡ããï¼ä»¶ããããã¾ãããï¼ä»¶ã¯ "oc" ã§ã¯ãªã "oç" ã§ãããTomcat ãåæ¢ãã¾ãã
test æã®åå¾ä»¶æ°ã確èªãã¾ããsrc/main/resources ã®ä¸ã® logback-develop.xml ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ããå¾ãtest ã¿ã¹ã¯ãå®è¡ãã¾ããtest æã¯ï¼ä»¶ããåå¾ãã¦ãããã"oç" ã§ã¯ããããã¦ãã¾ããã§ããã
ãRun 'Tests in 'ksbysample...' with Coverageãã bootRun ã¿ã¹ã¯ã§å®è¡ããæ㯠"oc" ã§æ¤ç´¢ããæã« "oç" ã®ãã¼ã¿ãããããã¾ãããtest ã¿ã¹ã¯ã§å®è¡ããæ㯠"oç" ã®ãã¼ã¿ã¯ãããããªãããã§ãã
調ã¹ãçµæã以ä¸ã®ãã¨ãåããã¾ããã
- Collation 㯠utf8_bin ã«ããã°å®å ¨ä¸è´ããæã ããããããããã«ãªãã¾ãã
- Collation 㯠create database ã®æã« default å¤ãè¨å®ãããã¨ãå¯è½ã§ããæ¢ã«å¥ã® Collation ã§ä½æããããã¼ãã«ã®ã«ã©ã ã® Collation ãå¤æ´ããæã«ã¯ãåã ã®ã«ã©ã æ¯ã«å¤æ´ããå¿ è¦ãããã¾ãã
IntelliJ IDEA 㧠test ã¿ã¹ã¯ã®æã ãæ¤ç´¢æ¹æ³ãå¤ããçç±ã¯åããã¾ããã§ãããåã ã®ã«ã©ã æ¯ã«è¨å®ãå¤æ´ããå¿ è¦ããããããã®ã§ãä»å㯠LocalName ã ã以ä¸ã® SQL ãå®è¡ãã¦è¨å®ãå¤æ´ãã¾ãã
ALTER TABLE country modify column LocalName char(45) character set 'utf8' COLLATE 'utf8_bin' not null;
LocalName ã® Collation ã utf8_bin ã«å¤æ´ããã¾ããã
å度 build ã¿ã¹ã¯ãå®è¡ãã¾ãããã ãä»åº¦ã¯ LocalName like '%oc%' ã§ã¯ï¼ä»¶ãããããããªããªãã¾ãã®ã§ãæåã« src/test/java/ksbysample/webapp/basic/web ã®ä¸ã® CountryListControllerTest.java ã ãªã³ã¯å ã®ãã®ï¼ã®å 容 ã«å¤æ´ãã¾ããå¤æ´å¾ãbuild ã¿ã¹ã¯ãå®è¡ãã¾ããä»åº¦ã¯ BUILD SUCCESSFUL ã表示ããã¾ããã
ãRun 'Tests in 'ksbysample...' with Coverageããé¸æãã¦ãã¹ããå®è¡ãã@Ignore ã¢ããã¼ã·ã§ã³ãä»å ãã¦ããªããã¹ããå ¨ã¦æåãããã¨ã確èªãã¾ãã
commitãGitHub 㸠Pushã1.0.x-testcountrylist -> 1.0.x 㸠Pull Requestã1.0.x ã§ãã¼ã¸ã1.0.x-testcountrylist ãã©ã³ããåé¤ãããã¾ãã
â»commit æã« Code Analysis ã®ãã¤ã¢ãã°ã表示ããã¾ããããã¹ãã¯ã©ã¹ã«ãã¦ãããã¹ãã¯ã©ã¹ã§ãã¹ãã¡ã½ããããªã親ã¯ã©ã¹ã使ç¨ããã¦ããªãã¨ãã Warning ãªã®ã§ãç¡è¦ãã¦ãCommitããã¿ã³ãã¯ãªãã¯ãã¾ãã
èå¯
product, develop ã¢ã¼ã以å¤ã« unittest ã®ã¢ã¼ããä½æãã¦ãunittest ã¢ã¼ãã®æ㯠Spring MVC ã® DEBUG åºåã log4jdbc-log4j2 ã®ãã°åºåãç¡å¹ã«ããæ¹ãããã¨æãã¾ãã ( ãã以å¤ã¯ develop ã¨åãè¨å®ã«ãã¾ã )ããã°ãåºåãããªããªãã¨ã¦ããããã¹ãã®ã¹ãã¼ããé¡èã«ä¸ããã¾ãã
MockMvc ã¯ä¾¿å©ãªã®ã§ãããandExpect ã¡ã½ãã㧠Model ã FieldError ã®ãã¼ã¿ããã§ãã¯ãã ResultMatcheres ã¯ã©ã¹ãä»ã²ã¨ã¤ã§ãæ¨æºã®ãã®ã ãã§ã¯è©³ç´°ãªãã¹ããåºæ¥ã¾ãããååã¯ãæ¨æºã§ç¨æããã¦ããªããã¨ããããã¾ã§ããå¿ è¦ã¯ãªãã®ããããã¾ããããã¨æ¸ãã¾ãããã便å©ãª ResultMatcheres ã¯ã©ã¹ãæããæ¹ããã¹ããããããããããã¹ãã«å¯¾ããå®å¿æãå¢ãã¨æãã¾ããèªåã§ä½æããããå¤é¨ã®ã©ã¤ãã©ãªã§ä½ããªããæ¢ãã¦ã¿ãããããã¨æãã¾ãã
ä»åæéãããã£ãçç±ã¨ã¯ï¼
MySQL ã®æåã³ã¼ãé¢é£ã®è¨å®ãå ¨ç¶åãããªãã¦è¦å´ãã¾ãããExample ã¨ãã¦ç¨æããã¦ãã world ãã¼ã¿ãã¼ã¹ã¯ InnoDBï¼utf8 ã§ä½ãç´ãã¦æ¬²ããã§ã ( å人çã«ã¯ Collation ãããã©ã«ã㯠utf8_bin ã«ãã¦æ¬²ããã§ã )ã
DbUnit ã空ã®ãã¼ã¿ãå ¥ããããªããã¨ããã®ãåãããªãã¦è¦å´ãã¾ãããç¹ã«ããã¯ã¢ãã/ãªã¹ãã¢ã®å ´åã«ãDbUnit ã§ãã¡ã¤ã«ã«åºåãããã¼ã¿ã DbUnit ã§ãã®ã¾ã¾ã§ã¯æ»ããªããã¨ããç¹ã«æ°ã¥ãã®ã«æéããããã¾ããã
ãã¹ãã¯ã©ã¹ã¯å ã«ãã£ã¨æ¸ãã¦åããã®ãåºæ¥ãã®ã§ãããã¯ã£ããè¨ã£ã¦åé·ã§ãã£ã¨ç°¡æ½ã«æ¸ãããã¨æã CustomModelResultMatchers ã¯ã©ã¹ãä½ã£ã¦ãã¦æéããããã¾ãããã§ã Spring Expression Language (SpEL) ã¯ä»ã«ãå¿ç¨ã§ããæ°ãããã®ã§ãæéãããã£ã¦ã調ã¹ã¦è¯ãã£ãã¨æã£ã¦ãã¾ãã
次åã¯ããã
æ¤ç´¢ç»é¢ ( Spring Data JPA ç ) ãä½æããåã«ã以ä¸ã®å¯¾å¿ãé²ãã¾ããä¸åº¦ã§ããã¨ã¾ãæéãããããããããªãã®ã§ãå°åºãã§é²ãã¦ã¿ãã¤ããã§ãã
- ç»é²ç»é¢ ( å ¥åâ確èªâå®äº ) ã®ãã¹ãã¯ã©ã¹ããã¹ãã¯ã©ã¹ã§æ§é åãã¦ãDB ã®ããã¯ã¢ãã/ãªã¹ãã¢ãè¡ããã¹ããæä½éãªãã®ã«ãªãããã«ãã¾ãã
- unittest ã¢ã¼ããä½æãã¦ã¦ããããã¹ãã®ã¹ãã¼ãã¢ãããå³ãã¾ãã
- 以åãã©ã³ã¶ã¯ã·ã§ã³ã®æ¤è¨¼ãããæã«è¦ã¤ãããè¨å®ãã¡ã¤ã«ã«ãããã©ã³ã¶ã¯ã·ã§ã³ã®è¨å®ãåæ ãã¾ãã
ã½ã¼ã¹ã³ã¼ã
country.csv
"Code","Name","Continent","Region","SurfaceArea","IndepYear","Population","LifeExpectancy","GNP","GNPOld","LocalName","GovernmentForm","HeadOfState","Capital","Code2" "ABW","Aruba","North America","Caribbean",193.00,[null],103000,78.4,828.00,793.00,"Aruba","Nonmetropolitan Territory of The Netherlands","Beatrix",129,"AW" "AFG","Afghanistan","Asia","Southern and Central Asia",652090.00,1919,22720000,45.9,5976.00,[null],"Afganistan/Afqanestan","Islamic Emirate","Mohammad Omar",1,"AF" "AGO","Angola","Africa","Central Africa",1246700.00,1975,12878000,38.3,6648.00,7984.00,"Angola","Republic","José Eduardo dos Santos",56,"AO" "AIA","Anguilla","North America","Caribbean",96.00,[null],8000,76.1,63.20,[null],"Anguilla","Dependent Territory of the UK","Elisabeth II",62,"AI" "ALB","Albania","Europe","Southern Europe",28748.00,1912,3401200,71.6,3205.00,2500.00,"Shqipëria","Republic","Rexhep Mejdani",34,"AL" (.....以ä¸ãçç¥.....)
table-ordering.txt
user user_role country
- æå¾ã« country ã追å ãã¾ãã
build.gradle
buildscript { repositories { jcenter() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.0.RELEASE") classpath("org.springframework:springloaded:1.2.1.RELEASE") } } apply plugin: 'java' apply plugin: 'spring-boot' apply plugin: 'idea' jar { baseName = 'ksbysample-webapp-basic' version = '0.0.1-SNAPSHOT' } idea { module { inheritOutputDirs = false outputDir = file("$buildDir/classes/main/") } } repositories { jcenter() maven { url "http://oss.sonatype.org/content/groups/public/" } } dependencies { def springBootVersion = '1.2.2.RELEASE' compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") compile("org.springframework.boot:spring-boot-starter-thymeleaf:${springBootVersion}") compile("org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}") compile("org.springframework.boot:spring-boot-starter-security:${springBootVersion}") compile("mysql:mysql-connector-java:5.1.34") compile("org.mybatis:mybatis:3.2.8") compile("org.mybatis:mybatis-spring:1.2.2") compile("org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16") compile("org.codehaus.janino:janino:2.7.5") compile("org.apache.commons:commons-lang3:3.3.2") compile("org.projectlombok:lombok:1.14.8") testCompile("org.springframework.boot:spring-boot-starter-test:${springBootVersion}") testCompile("org.springframework.security:spring-security-test:4.0.0.RC2") testCompile("org.dbunit:dbunit:2.5.0") testCompile("org.yaml:snakeyaml:1.16-SNAPSHOT") } bootRun { jvmArgs = ['-Dspring.profiles.active=develop'] } test { jvmArgs = ['-Dspring.profiles.active=develop'] }
- repositories ã®ä¸ã«
maven { url "http://oss.sonatype.org/content/groups/public/" }
ã追å ãã¾ãã - dependencies ã®ä¸ã«
testCompile("org.yaml:snakeyaml:1.16-SNAPSHOT")
ã追å ãã¾ãã
countryListForm_empty.yaml
!!ksbysample.webapp.basic.web.CountryListForm code: name: continent: localName: page: 0 size: 5
countryListForm_code.yaml, countryListForm_name.yaml, countryListForm_continent.yaml, countryListForm_localName.yaml
â countryListForm_code.yaml
!!ksbysample.webapp.basic.web.CountryListForm code: JPN name: continent: localName: page: 0 size: 5
â countryListForm_name.yaml
!!ksbysample.webapp.basic.web.CountryListForm code: name: go continent: localName: page: 1 size: 5
â countryListForm_continent.yaml
!!ksbysample.webapp.basic.web.CountryListForm code: name: continent: Oceania localName: page: 5 size: 5
â countryListForm_localName.yaml
!!ksbysample.webapp.basic.web.CountryListForm code: name: continent: localName: oc page: 0 size: 5
CustomModelResultMatchers.java
package ksbysample.webapp.basic.test; import org.hamcrest.Matcher; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.test.web.servlet.ResultMatcher; import org.springframework.test.web.servlet.result.ModelResultMatchers; import org.springframework.ui.ModelMap; import java.util.regex.Pattern; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.springframework.test.util.MatcherAssertionErrors.assertThat; public class CustomModelResultMatchers extends ModelResultMatchers { public static CustomModelResultMatchers modelEx() { return new CustomModelResultMatchers(); } @SuppressWarnings("unchecked") public <T> ResultMatcher property(final String nameAndProperty, final Matcher<T> matcher) { return mvcResult -> { // <ã¤ã³ã¹ã¿ã³ã¹å>.<ããããã£å> ( ä¾: page.number ) ã®å½¢å¼ã®æååã // ã¤ã³ã¹ã¿ã³ã¹åã¨ããããã£åã«åå²ãã Pattern p = Pattern.compile("^(\\S+?)\\.(\\S+)$"); java.util.regex.Matcher m = p.matcher(nameAndProperty); assertThat(m.find(), is(true)); String name = m.group(1); String property = m.group(2); // ããããã£ã®å¤ãåå¾ãã¦ãã§ãã¯ãã ModelMap modelMap = mvcResult.getModelAndView().getModelMap(); Object object = modelMap.get(name); assertThat(object, is(notNullValue())); EvaluationContext context = new StandardEvaluationContext(object); ExpressionParser parser = new SpelExpressionParser(); Expression exp = parser.parseExpression(property); Object value = exp.getValue(context); assertThat((T) value, matcher); }; } }
- ã¤ã³ã¿ã¼ãã§ã¼ã¹ã¯ org.springframework.test.web.servlet.result.ModelResultMatchers ã®
public <T> ResultMatcher attribute(final String name, final Matcher<T> matcher)
ã¡ã½ãããåèã«ãã¾ããã
TestDataResource.java
â ãã®ï¼
@Override protected void before() throws Throwable { IDatabaseConnection conn = null; try { conn = new DatabaseConnection(dataSource.getConnection()); // ããã¯ã¢ãããåå¾ãã QueryDataSet partialDataSet = new QueryDataSet(conn); partialDataSet.addTable("user"); partialDataSet.addTable("user_role"); partialDataSet.addTable("country"); backupFile = File.createTempFile("world_backup", "xml"); FlatXmlDataSet.write(partialDataSet, new FileOutputStream(backupFile)); // ãã¹ããã¼ã¿ã«å ¥ãæ¿ãã IDataSet dataset = new CsvDataSet(new File("src/test/resources/testdata")); ReplacementDataSet replacementDataset = new ReplacementDataSet(dataset); replacementDataset.addReplacementObject("[null]", null); DatabaseOperation.CLEAN_INSERT.execute(conn, replacementDataset); } finally { if (conn != null) conn.close(); } }
ReplacementDataSet replacementDataset = new ReplacementDataSet(dataset);
ã¨replacementDataset.addReplacementObject("[null]", null);
ã追å ãã¾ããDatabaseOperation.CLEAN_INSERT.execute
ã®ç¬¬ï¼å¼æ°ã replacementDataset ã«å¤æ´ãã¾ãã
â ãã®ï¼
package ksbysample.webapp.basic.test; import org.dbunit.database.DatabaseConnection; import org.dbunit.database.IDatabaseConnection; import org.dbunit.database.QueryDataSet; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ReplacementDataSet; import org.dbunit.dataset.csv.CsvDataSet; import org.dbunit.dataset.xml.FlatXmlDataSet; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.dbunit.operation.DatabaseOperation; import org.junit.rules.ExternalResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.io.File; import java.io.FileOutputStream; @Component public class TestDataResource extends ExternalResource { @Autowired private DataSource dataSource; private File backupFile; @Override protected void before() throws Exception { IDatabaseConnection conn = null; try { conn = new DatabaseConnection(dataSource.getConnection()); // ããã¯ã¢ãããåå¾ãã QueryDataSet partialDataSet = new QueryDataSet(conn); partialDataSet.addTable("user"); partialDataSet.addTable("user_role"); partialDataSet.addTable("country"); backupFile = File.createTempFile("world_backup", "xml"); FlatXmlDataSet.write(partialDataSet, new FileOutputStream(backupFile)); // ãã¹ããã¼ã¿ã«å ¥ãæ¿ãã IDataSet dataset = new CsvDataSet(new File("src/test/resources/testdata")); ReplacementDataSet replacementDataset = new ReplacementDataSet(dataset); replacementDataset.addReplacementObject("[null]", null); DatabaseOperation.CLEAN_INSERT.execute(conn, replacementDataset); } finally { if (conn != null) conn.close(); } } @Override protected void after() { try { IDatabaseConnection conn = null; try { conn = new DatabaseConnection(dataSource.getConnection()); // ããã¯ã¢ãããããªã¹ãã¢ãã if (backupFile != null) { // IDataSet dataSet = new FlatXmlDataSetBuilder().build(backupFile); // DatabaseOperation.CLEAN_INSERT.execute(conn, dataSet); backupFile.delete(); backupFile = null; } } finally { if (conn != null) conn.close(); } } catch (Exception e) { e.printStackTrace(); } } }
- after ã¡ã½ããå
ã®
catch (Exception ignored) {}
âcatch (Exception e) { e.printStackTrace(); }
ã«å¤æ´ãã¦ã¨ã©ã¼å 容ãåºåãããããã«ãã¾ãã - country ãã¼ãã«ã®ãã¼ã¿ãæ»ãããã®ã§ãããã¯ã¢ãããããªã¹ãã¢ãã¦ããï¼è¡ãã³ã¡ã³ãã¢ã¦ããã¦æå ¥ãã country.csv ã®ãã¹ããã¼ã¿ãå ¥ã£ãã¾ã¾ã«ãªãããã«ãã¾ãã
- before ã¡ã½ããã® throws ç¯ã
Throwable
âException
ã«å¤æ´ãã¾ã ( ãã®ä¿®æ£ã¯åã«å人çãªå¥½ã¿ã§ã )ã
â ãã®ï¼
@Override protected void after() { try { IDatabaseConnection conn = null; try { conn = new DatabaseConnection(dataSource.getConnection()); // ããã¯ã¢ãããããªã¹ãã¢ãã if (backupFile != null) { IDataSet dataSet = new FlatXmlDataSetBuilder().build(backupFile); DatabaseOperation.CLEAN_INSERT.execute(conn, dataSet); backupFile.delete(); backupFile = null; } } finally { if (conn != null) conn.close(); } } catch (Exception e) { e.printStackTrace(); } }
- after ã¡ã½ããå ã®ã³ã¡ã³ãã¢ã¦ãããé¨åãå ã«æ»ãã¾ãã
â ãã®ï¼
package ksbysample.webapp.basic.test; import org.dbunit.database.DatabaseConnection; import org.dbunit.database.IDatabaseConnection; import org.dbunit.database.QueryDataSet; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.ReplacementDataSet; import org.dbunit.dataset.csv.CsvDataSet; import org.dbunit.dataset.xml.FlatXmlDataSet; import org.dbunit.dataset.xml.FlatXmlDataSetBuilder; import org.dbunit.operation.DatabaseOperation; import org.junit.rules.ExternalResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.io.File; import java.io.FileOutputStream; import java.nio.file.Files; @Component public class TestDataResource extends ExternalResource { @Autowired private DataSource dataSource; private File backupFile; @Override protected void before() throws Exception { IDatabaseConnection conn = null; try { conn = new DatabaseConnection(dataSource.getConnection()); // ããã¯ã¢ãããåå¾ãã QueryDataSet partialDataSet = new QueryDataSet(conn); partialDataSet.addTable("user"); partialDataSet.addTable("user_role"); partialDataSet.addTable("country"); ReplacementDataSet replacementDatasetBackup = new ReplacementDataSet(partialDataSet); replacementDatasetBackup.addReplacementObject("", "[null]"); backupFile = File.createTempFile("world_backup", "xml"); try (FileOutputStream fos = new FileOutputStream(backupFile)) { FlatXmlDataSet.write(replacementDatasetBackup, fos); } // ãã¹ããã¼ã¿ã«å ¥ãæ¿ãã IDataSet dataSet = new CsvDataSet(new File("src/test/resources/testdata")); ReplacementDataSet replacementDataset = new ReplacementDataSet(dataSet); replacementDataset.addReplacementObject("[null]", null); DatabaseOperation.CLEAN_INSERT.execute(conn, replacementDataset); } finally { if (conn != null) conn.close(); } } @Override protected void after() { try { IDatabaseConnection conn = null; try { conn = new DatabaseConnection(dataSource.getConnection()); // ããã¯ã¢ãããããªã¹ãã¢ãã if (backupFile != null) { IDataSet dataSet = new FlatXmlDataSetBuilder().build(backupFile); ReplacementDataSet replacementDatasetRestore = new ReplacementDataSet(dataSet); replacementDatasetRestore.addReplacementObject("[null]", null); DatabaseOperation.CLEAN_INSERT.execute(conn, replacementDatasetRestore); } } finally { if (backupFile != null) { Files.delete(backupFile.toPath()); backupFile = null; } try { if (conn != null) conn.close(); } catch (Exception ignored) {} } } catch (Exception e) { e.printStackTrace(); } } }
before ã¡ã½ããå ã§
ReplacementDataSet replacementDatasetBackup = new ReplacementDataSet(partialDataSet);
,replacementDatasetBackup.addReplacementObject("", "[null]");
ã®ï¼è¡ã追å ãããã®å¾ã® FlatXmlDataSet.write ã®ç¬¬ï¼å¼æ°ã replacementDatasetBackup ã«å¤æ´ãã¾ããããã¯ã¢ãããã¡ã¤ã«ããªã¼ãã³ãããã¾ã¾ã§ãafter ã¡ã½ããã§åé¤ã§ãã¦ããªããã¨ã«æ°ã¥ãã¾ãããåå 㯠FlatXmlDataSet.write ã®ç¬¬ï¼å¼æ°ã«
new FileOutputStream(backupFile)
ã¨æ¸ãã¦ãã¦ãã¯ãã¼ãºãã¦ããªãããã§ãããFlatXmlDataSet.write ã®ç¬¬ï¼å¼æ°ãnew FileOutputStream(backupFile)
âfos
ã¸å¤æ´ããfos
㯠try-with-resources æã§çæãã¦èªåçã«ã¯ãã¼ãºãããããã«ãã¾ããã- before ã¡ã½ããå
ã®è¨è¿°ã after ã¡ã½ããå
ã¨è¨è¿°ãçµ±ä¸ããã¦ããªãã£ããã¨ã«æ°ã¥ããã®ã§ã
IDataSet dataset
âIDataSet dataSet
ã«å¤æ´ãã¾ãã - after ã¡ã½ããå
ã§
ReplacementDataSet replacementDatasetRestore = new ReplacementDataSet(dataSet);
,replacementDatasetRestore.addReplacementObject("[null]", null);
ã®ï¼è¡ã追å ãããã®å¾ã® DatabaseOperation.CLEAN_INSERT.execute ã®ç¬¬ï¼å¼æ°ã replacementDatasetRestore ã«å¤æ´ãã¾ãã - ã¨ã©ã¼çºçæã«ããã¯ã¢ãããã¡ã¤ã«ãåé¤ããã¦ããªããã¨ã«æ°ã¥ããã®ã§ãããã¯ã¢ãããã¡ã¤ã«ãåé¤ããå¦çã finally å
ã«ç§»åãã¾ããã¾ãåé¤ããæ¹æ³ã
backupFile.delete()
âFiles.delete(backupFile.toPath())
ã¸å¤æ´ãã¾ããåé¤ã¨ã©ã¼ã®æã«å¾è ã®æ¸ãæ¹ã ã¨ä¾å¤ã throw ããã¦ãã¨ã©ã¼ã®åå ãæ確ã«åããããã§ãã if (conn != null) conn.close();
ãtry { ... } catch (Exception ignored) {}
ã§å²ã¿ãã¨ã©ã¼çºçæã«ä»ã®å¦çãã¹ããããããªãããã«ãã¾ãã- finally, catch ã { ã¨åãè¡ã«ãã£ãã次ã®è¡ã«ãã£ããã¨çµ±ä¸ããã¦ããªãã£ãã®ã§ãåãè¡ã«æ¸ãããä¿®æ£ãã¾ãã
logback-develop.xml
â ãã®ï¼
<?xml version="1.0" encoding="UTF-8"?> <included> <!-- Spring MVC --> <logger name="org.springframework.web" level="ERROR"/> <!-- log4jdbc-log4j2 --> <logger name="jdbc" level="ERROR"/> <!--<logger name="jdbc.sqlonly" level="DEBUG"/>--> <!--<logger name="jdbc.sqltiming" level="INFO"/>--> <!--<logger name="jdbc.audit" level="INFO"/>--> <!--<logger name="jdbc.resultset" level="ERROR"/>--> <!--<logger name="jdbc.resultsettable" level="ERROR"/>--> <!--<logger name="jdbc.connection" level="DEBUG"/>--> </included>
- org.springframework.web ã® leve ã
DEBUG
âERROR
ã¸å¤æ´ãã¾ãã - log4jdbc-log4j2ãã®ãã°è¨å®ã«
<logger name="jdbc" level="ERROR"/>
ã追å ãããã®ä¸ã®åå¥ã®è¨å®ãå ¨ã¦ã³ã¡ã³ãã¢ã¦ããã¾ãã
â ãã®ï¼
<?xml version="1.0" encoding="UTF-8"?> <included> <!-- Spring MVC --> <logger name="org.springframework.web" level="DEBUG"/> <!-- log4jdbc-log4j2 --> <logger name="jdbc.sqlonly" level="DEBUG"/> <logger name="jdbc.sqltiming" level="INFO"/> <logger name="jdbc.audit" level="INFO"/> <logger name="jdbc.resultset" level="ERROR"/> <logger name="jdbc.resultsettable" level="ERROR"/> <logger name="jdbc.connection" level="DEBUG"/> </included>
- å ¨ã¦ã®è¨å®ãå ã«æ»ãã¾ãã
â ãã®ï¼
<?xml version="1.0" encoding="UTF-8"?> <included> <!-- Spring MVC --> <logger name="org.springframework.web" level="DEBUG"/> <!-- log4jdbc-log4j2 --> <logger name="jdbc.sqlonly" level="DEBUG"/> <logger name="jdbc.sqltiming" level="INFO"/> <logger name="jdbc.audit" level="INFO"/> <!--<logger name="jdbc.resultset" level="ERROR"/>--> <!--<logger name="jdbc.resultsettable" level="ERROR"/>--> <logger name="jdbc.resultset" level="DEBUG"/> <logger name="jdbc.resultsettable" level="DEBUG"/> <logger name="jdbc.connection" level="DEBUG"/> </included>
- log4jdbc-log4j2 ã® jdbc.resultset, jdbc.resultsettable ã® level ã ERROR â DEBUG ã«å¤æ´ãã¾ãã
drop_and_create_user.sql
drop table user; create table user ( id varchar(32) not null , password varchar(128) not null , enabled tinyint not null default 1 , constraint pk_user primary key (id) ); drop table user_role; create table user_role ( id varchar(32) not null , role varchar(32) not null , constraint pk_user_role primary key (id) ); insert into user values('test', '$2a$10$5hPduqwwdl5ZhAeOEKP18eMJj2DdVv8AWaYeU0VlRU2FcXcA.qeSC', 1); insert into user_role values('test', 'USER'); commit;
CountryListControllerTest.java
â ãã®ï¼
package ksbysample.webapp.basic.web; import ksbysample.webapp.basic.Application; import ksbysample.webapp.basic.test.SecurityMockMvcResource; import ksbysample.webapp.basic.test.TestDataResource; import ksbysample.webapp.basic.test.TestHelper; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.yaml.snakeyaml.Yaml; import static ksbysample.webapp.basic.test.CustomModelResultMatchers.modelEx; import static org.hamcrest.Matchers.is; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; public class CountryListControllerTest { @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class éèªè¨¼æã®å ´å { @Rule @Autowired public SecurityMockMvcResource secmvc; @Test public void ãã°ã¤ã³ç»é¢ã«ãªãã¤ã¬ã¯ãããã() throws Exception { secmvc.nonauth.perform(get("/countryList")) .andExpect(status().isFound()) .andExpect(redirectedUrl("http://localhost/")); } } public static class èªè¨¼æã®å ´å { @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class ç»é¢åæ表示ã®å ´å { @Rule @Autowired public SecurityMockMvcResource secmvc; @Test public void æ¤ç´¢ä¸è¦§ç»é¢ã表示ããã() throws Exception { secmvc.auth.perform(get("/countryList")) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")); } } @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class æ¤ç´¢æ¡ä»¶ã¯ä½ãå ¥åããªãã§æ¤ç´¢ããå ´å { @Rule @Autowired public TestDataResource testDataResource; @Rule @Autowired public SecurityMockMvcResource secmvc; // ãã¹ããã¼ã¿ private CountryListForm countryListFormEmpty = (CountryListForm) new Yaml().load(getClass().getResourceAsStream("countryListForm_empty.yaml")); @Test public void æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ãã¼ã¸ç®ã表示ããã() throws Exception { secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormEmpty) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(48))) .andExpect(modelEx().property("page.numberOfElements", is(5))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(false))); } @Test public void æ¤ç´¢æ¡ä»¶ã¯ãã®ã¾ã¾ã§ï¼ãã¼ã¸ç®ã¸() throws Exception { this.countryListFormEmpty.setPage(1); secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormEmpty) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(modelEx().property("page.number", is(1))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(48))) .andExpect(modelEx().property("page.numberOfElements", is(5))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(false))) .andExpect(modelEx().property("ph.hiddenNext", is(false))); } @Test public void æ¤ç´¢æ¡ä»¶ã¯ãã®ã¾ã¾ã§æçµãã¼ã¸ã¸() throws Exception { this.countryListFormEmpty.setPage(47); secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormEmpty) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(modelEx().property("page.number", is(47))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(48))) .andExpect(modelEx().property("page.numberOfElements", is(4))) .andExpect(modelEx().property("ph.page1PageValue", is(43))) .andExpect(modelEx().property("ph.hiddenPrev", is(false))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); } } @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) @WebAppConfiguration public static class æ¤ç´¢æ¡ä»¶ãå ¥åãã¦æ¤ç´¢ããå ´å { @Rule @Autowired public TestDataResource testDataResource; @Rule @Autowired public SecurityMockMvcResource secmvc; // ãã¹ããã¼ã¿ private CountryListForm countryListFormCode = (CountryListForm) new Yaml().load(getClass().getResourceAsStream("countryListForm_code.yaml")); private CountryListForm countryListFormName = (CountryListForm) new Yaml().load(getClass().getResourceAsStream("countryListForm_name.yaml")); private CountryListForm countryListFormContinent = (CountryListForm) new Yaml().load(getClass().getResourceAsStream("countryListForm_continent.yaml")); private CountryListForm countryListFormLocalName = (CountryListForm) new Yaml().load(getClass().getResourceAsStream("countryListForm_localName.yaml")); @Test public void Codeã®ã¿å ¥åãã¦æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ä»¶ããããã() throws Exception { secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormCode) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(1))) .andExpect(modelEx().property("page.numberOfElements", is(1))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); } @Test public void Nameã®ã¿å ¥åãã¦æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ä»¶ããããã() throws Exception { secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormName) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(model().attributeExists("page")) .andExpect(model().attributeExists("ph")) .andExpect(modelEx().property("page.number", is(1))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(2))) .andExpect(modelEx().property("page.numberOfElements", is(3))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(false))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); } @Test public void Continentã®ã¿å ¥åãã¦æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ä»¶ããããã() throws Exception { secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormContinent) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(modelEx().property("page.number", is(5))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(6))) .andExpect(modelEx().property("page.numberOfElements", is(3))) .andExpect(modelEx().property("ph.page1PageValue", is(1))) .andExpect(modelEx().property("ph.hiddenPrev", is(false))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); } @Test public void LocalNameã®ã¿å ¥åãã¦æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ä»¶ããããã() throws Exception { secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormLocalName) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(1))) .andExpect(modelEx().property("page.numberOfElements", is(5))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); } } } }
â ãã®ï¼
@Test public void LocalNameã®ã¿å ¥åãã¦æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ä»¶ããããã() throws Exception { secmvc.auth.perform(TestHelper.postForm("/countryList", this.countryListFormLocalName) .with(csrf()) ) .andExpect(status().isOk()) .andExpect(content().contentType("text/html;charset=UTF-8")) .andExpect(view().name("countryList")) .andExpect(xpath("/html/head/title").string("æ¤ç´¢/ä¸è¦§ç»é¢")) .andExpect(modelEx().property("page.number", is(0))) .andExpect(modelEx().property("page.size", is(5))) .andExpect(modelEx().property("page.totalPages", is(1))) .andExpect(modelEx().property("page.numberOfElements", is(2))) .andExpect(modelEx().property("ph.page1PageValue", is(0))) .andExpect(modelEx().property("ph.hiddenPrev", is(true))) .andExpect(modelEx().property("ph.hiddenNext", is(true))); }
- LocalName like '%oc%' ã«ããããããã¼ã¿ã¯ï¼ä»¶ãããªãã®ã§ãããã«åããã¾ãã
- ã¡ã½ããåã
LocalNameã®ã¿å ¥åãã¦æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ä»¶ããããã
âLocalNameã®ã¿å ¥åãã¦æ¤ç´¢ãã¿ã³ãã¯ãªãã¯ããã¨ï¼ä»¶ããããã
ã«å¤æ´ãã¾ãã .andExpect(modelEx().property("page.numberOfElements", is(5)))
â.andExpect(modelEx().property("page.numberOfElements", is(2)))
ã«å¤æ´ãã¾ãã
å±¥æ´
2015/03/16
åççºè¡ã