Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
΢·þÎñ¼Ü¹¹¡ª×Ô¶¯»¯²âÊÔÈ«Á´Â·Éè¼Æ
 
  5616  次浏览      27
 2018-7-23
 

 

±à¼­ÍƼö:

±¾ÎÄÀ´×ÔÓÚ51cto£¬±¾ÎÄÖ÷Òª½éÉÜÁËÔÚ΢·þÎñ¼Ü¹¹ÏµIJâÊÔ¸´ÔÓ¶ÈÒÔ¼°Ð§ÂʵÄÎÊÌâºÍ×Ô¶¯»¯²âÊÔ½×¶Î mock ÐèÇóµÈÏà¹ØÖªÊ¶¡£

  • ±³¾°
  • ±»ºöÊÓµÄÈí¼þ¹¤³Ì»·½Ú - DEVTESTOPS
  • ΢·þÎñ¼Ü¹¹Ï²âÊÔ¸´ÔӶȺÍЧÂÊÎÊÌâ
  • ¿ª·¢½×¶Î unitTest mock ÍⲿÒÀÀµ
  • Á¬µ÷½×¶Î mock ÍⲿÒÀÀµ
  • ×Ô¶¯»¯²âÊÔ½×¶Î mock ÐèÇó
  • autoTest Mock Gateway ¸¡³öË®Ãæ
  • ÇáÁ¿¼¶°æ±¾ÊµÏÖ
    • ÕûÌåÂß¼­¼Ü¹¹
    • ½« mock parameter ÄÉÈë·þÎñ¿ò¼Ü±ê×¼ request contract
    • ʹÓà AOP + RestEasy HttpClientRequest SPI ³õ²½ÊµÏÖ Mock
  • ×ܽá

±³¾°

´Ó SOA ¼Ü¹¹µ½ÏÖÔÚ´óÐÐÆäµÀµÄ΢·þÎñ¼Ü¹¹£¬ÏµÍ³Ô½²ðԽС£¬ÕûÌå¼Ü¹¹µÄ¸´ÔÓ¶ÈÒ²ÊÇÖ±ÏßÉÏÉý£¬ÎÒÃÇÒ»Ö±ÀÏÉú³£Ì¸µÄ΢·þÎñ¼Ü¹¹Ïµļ¼ÊõÄѵ㼰½â¾ö·½°¸Ò²ÈÕ½¥³ÉÊ죨°üÀ¨µäÐ͵ÄÊý¾ÝÒ»ÖÂÐÔ£¬ÏµÍ³µ÷ÓôøÀ´µÄÒ»ÖÂÐÔÎÊÌ⣬»¹ÊÇ¿ç½Úµã¿ç»ú·¿¸´ÖÆ´øÀ´µÄÒ»ÖÂÐÔÎÊÌâ¶¼ÓÐÁ˺ܶà½â¾ö·½°¸£©£¬µ«ÊÇÓÐÒ»¸ö»·½ÚÎÒÃÇÃ÷ÏÔºöÂÔÁË¡£

ÔÚÏÖÔÚµÄ΢·þÎñ¼Ü¹¹Ç÷ÊÆÏ£¬Î¢·þÎñÔÚÔËά²ãÃæºÍ×Ô¶¯»¯²¿Êð·½Ãæ»ù±¾ÉÏÊDZȽÏÍêÉÆÁË¡£´ÓÎÒ¸öÈ˾­ÑéÀ´¿´£¬ÉϲãµÄ¿ª·¢¡¢²âÊÔ¶Ô΢·þÎñ¼Ü¹¹´øÀ´µÄ¾Þ´ó±ä»¯»¹ÔÚ·´Ó¦ºÍѧϰÖС£

¿ª·¢²ãÃæÌÖÂÛ΢·þÎñµÄ¸ü¶àÊÇ¿ò¼Ü¡¢ÖÎÀí¡¢ÐÔÄܵȣ¬µ«ÊÇ´ÓÍêÕûµÄÈí¼þ¹¤³ÌÀ´¿´ÎÒÃÇÑÏÖØÈ±Ê§·ÖÎö¡¢Éè¼ÆÖªÊ¶£¬ÕâÒ²ÊÇÎÒÃÇÏÖÔڵŤ³ÌʦÆÕ±éȱ·¦µÄ¼¼Êõ¡£

ÎÒÃǾ­³£»á·¢ÏÖÒ»µ©ÄãÏëÖØ¹¹µã¶«Î÷ÊǶàôµÄ¼èÄÑ£¬¾ÍÊÇÒòΪÔÚ³õÆÚ¹¹ÔìÕâ¶°½¨ÖþµÄʱºòÑÏÖØÈ±Ê§ÁËͨÅ̵ķÖÎö¡¢Éè¼Æ£¬×îÖÕµ¼ÖÂÕâ¸ö½¨ÖþÂýÂý½©»¯×îºóÈ˼ûÈËÅ£¬ÒòΪËûÖð½¥±ä³ÉÒ»¸ö¹ÖÎï¡££¨±ÈÈ磬¿ª·¢ºÜÉÙд unitTest £¬ÎÒÃÇ×ÜÊǺöÊÓµ¥Ôª²âÊÔ±³ºó²úÉúµÄÈí¼þ¹¤³ÌµÄ¼ÛÖµ¡££©

±»ºöÊÓµÄÈí¼þ¹¤³Ì»·½Ú ¡ª DEVTESTOPS

ÎÒÃÇÓÐûÓз¢ÏÖÒ»¸öÏÖÏó£¬ÔÚÕû¸öÈí¼þ¹ý³ÌÀ²âÊÔÕâ¸ö»·½ÚÈÝÒ×±»ºöÊÓ¡£ÈκÎÒ»ÖÖÈí¼þ¹¤³ÌÄ£ÐͶ¼ÓÐ QA »·½Ú£¬µ«ÊÇÕâ¸ö»·½ÚËÆºõºÜ±¡ºÜÈõ£¬Ä¿Ç°ÎÒÃǾø´ó¶àÊý¹¤³Ìʦ¡¢¼Ü¹¹Ê¦¶¼ÑÏÖØµÍ¹ÀÁËÕâ¸ö»·½ÚµÄÁ¦Á¿ºÍ¼ÛÖµ£¬»¹Í£ÁôÔÚÎÞ¼¼Êõº¬Á¿£¬ÊÖ¶¯¹¦ÄܲâÊԵͼ¶Ð§ÂÊÓ¡ÏóÀï¡£

ÕâÖ÷ÒªÊDzâÊÔÕâ¸ö½ÇÉ«Õû¸ö¼¼ÊõÌåϵ¡¢¹¤³Ì»¯ÄÜÁ¦Æ«Èõ£¬Ò»²¿·ÖÊǿ͹۴󻷾³ÎÊÌ⣬»¹ÓÐÒ»²¿·Ö×ÔÉíÎÊÌ⣬ûÓÐÈÃ×Ô¼º×ß³öÈ¥£¬¶àȥѧϰÕû¸ö¹¤³Ì»¯µÄ¼¼Êõ£¬¶àÈ¥Á˽⿪·¢µÄ¼¼Êõ£¬Éú²úÉϵÄÎïÀí¼Ü¹¹£¬Õâ»áÓÐÖúÓÚ²âÊÔ·Å´ó×Ô¼ºµÄÉùÒô¡£

µ¼Ö²âÊÔ»·½ÚÔÚ¹úÄÚÕû¸öÉè¼Æ´´Ð±¡ÈõµÄÔ­Òò»¹ÓÐÒ»¸öÖ÷ÒªÔ­Òò¾ÍÊÇ£¬¿ª·¢¹¤³ÌʦÆÕ±éûÓÐÍêÕûµÄ¹¤³Ì»ù´¡¡£ÔÚ¹úÍâIT·¢´ï¹ú¼Ò£¬ÈÕ±¾¡¢ÃÀ¹úµÈ£¬Ò»¸öºÏ¸ñµÄ¿ª·¢¹¤³Ìʦ¡¢²âÊÔ¹¤³Ìʦ¶¼ÊDZ߽çÄ£ºýµÄ£¬×Ô¼º¿ª·¢²úÆ·×Ô¼º²âÊÔ£¬ÕâÐèÒªÇл»Ë¼Î¬Ä£Ê½£¬ÐèҪͬʱ¾ß±¸ÕâÁ½ÖÖÄÜÁ¦£¬µ«ÊÇÕâ²ÅÊÇÕû¸öÈí¼þ¹¤³ÌµÄÍêÕûÁ÷³Ì¡£

ÎÒÃÇÓÐûÓÐÏë¹ýÒ»¸öÎÊÌ⣬ΪʲôÏÖÔÚ´ó¼Ò¶¼ÔÚ̸ÂÛ DevOps£¬¶ø²»ÊÇ DevTestOps£¬ÎªÊ²Ã´Æ«Æ«Ìø¹ý²âÊÔÕâ¸ö»·½Ú£¬ÄѵÀ¿ª·¢µÄϵͳÐèÒª¾ß±¸Á¼ºÃµÄ¿ÉÔËάÐԾͲ»ÐèÒª¿É²âÊÔÐÔÂ𣬿ª·¢ÐèÒª¾ß±¸ÔËάÄÜÁ¦£¬ÔËάÐèÒª¾ß±¸¿ª·¢ÄÜÁ¦£¬ÎªÊ²Ã´²âÊÔ»·½ÚºöÂÔÁË¡£

ÎÒÃÇ¶Ô QA »·½ÚµÄÇáÊÓ£¬¶Ô²âÊÔ½ÇÉ«µÄ²»ÖØÊÓÆäʵ´øÀ´µÄ¸±×÷ÓÃÊǷdz£´óµÄ¡£

΢·þÎñ¼Ü¹¹Ï²âÊÔ¸´ÔӶȺÍЧÂÊÎÊÌâ

΢·þÎñµÄ²ð·ÖÁ£¶ÈÒª±È SOA ϸÁ˺ܶ࣬´ÓÈÝÆ÷»¯¾µÏñ×Ô¶¯²¿ÊðÀ´ºâÁ¿£¬ÊDzðСÁËÖ®ºóºÜ·½±ã£¬µ«ÊDzðСÁËÖ®ºó»á¸øÕû¸ö¿ª·¢¡¢²âÊÔ»·½ÚÔö¼ÓºÜ´óµÄ¸´ÔӶȺÍЧÂÊÎÊÌâ¡£

ÔÚ SOA ʱÆÚ£¬ÆõÔ¼Çý¶¯ Õâ¸öÔ­ÔòÔÚ΢·þÎñÀïÒ²Ò»ÑùÊÊÓ㬿粿ÃÅÐèÇó¶¨ÒåºÃÆõÔ¼Äã¾Í¿ÉÒÔÏÈ¿ª·¢ÉÏÏßÁË¡£µ«ÊÇÕâ¸öÀïÃæ×î´óµÄÎÊÌâ¾ÍÊǵ±Ç°ÏµÍ³µÄ²¿·ÖÁ¬µ÷ÎÊÌâºÍ×Ô¶¯»¯»Ø¹éÎÊÌ⣬Èç¹ûÊÇÐÂϵͳÉÏÏß»¹ÐèÒª×öÐÔÄÜѹ²â£¬ÕâÍⲿµÄÒÀÀµÈçºÎ½â¾ö¡£

Ò²ÐíÎÒÃÇ»á˵£¬²»ÊÇÓ¦¸ÃÒÀÀµ·½ÏÈready£¬È»ºóÎÒÃǽô½Ó׎øÐвâÊÔ¡¢·¢²¼Âð¡£Èç¹ûÊÇÒµÎñ¡¢¼Ü¹¹ºÏÀíµÄÇé¿öÏ£¬ÕâÖÖ³¡¾°×î´óµÄÎÊÌâ¾ÍÊÇÎÒÃǵÄÏîÄ¿ÈÝÒ×±»ÒÀÀµ·½Ç£ÖÆ£¬Õâ»á´øÀ´ºÜ¶àÎÊÌ⣬±ÈÈ磬Ñз¢ÈËÔ±ÐèÒªÇл»³öÀ´×öÆäËûÊÂÇ飬branch Ò»Ö±¹Ò×Å£¬²»ÖªµÀÄÄÌìͻȻÀ´ÕÒÄã˵¿ÉÒÔ¶Ô½ÓÁË£¬Ò²ÐíÕâÒѾ­¹ýÈ¥Ò»¸öÔ»òÕ߸ü¾Ã£¬ÕâÖÖ·½Ê½Ò»µ©Ñø³Éϰ¹ßÐÔÑз¢Á÷³Ì¾ÍºÜÈÝÒײúÉúÏßÉÏ BUG ¡£

»¹ÓÐÒ»ÖÖÇé¿öÒ²ÊǺÏÀíµÄÇé¿ö¾ÍÊÇÆ½Ì¨Ìṩ·½ÐèÒªµ÷ÓÃÒµÎñ·½µÄ½Ó¿Ú£¬ÕâÀïÃæÓÐÒ»°ãµ÷ÓÃµÄ callback ½Ó¿Ú¡¢½»Ò×Á´Â·É쵀 marketing ½Ó¿Ú¡¢ÅäËÍ routing ½Ó¿ÚµÈ¡£

ÕâÀï¸ø´ó¼Ò·ÖÏíÎÒÃÇĿǰÕýÔÚ½øÐÐÖÐµÄ marketing-cloud (ÓªÏúÔÆ) ¹æÔòÒýÇæ ÏîÄ¿¡£

marketing-cloud ÌṩÁËһЩӪÏúÀàÒµÎñ£¬ÓÐ ÍŹº¡¢ÓÅ»Ýȯ¡¢´ÙÏú µÈ£¬µ«ÊÇÎÒÃǵÄÒµÎñ·½ÐèÒªÓÐ×Ô¼º¸öÐÔ»¯µÄÓªÏú»î¶¯Íæ·¨£¬ÎÒÃÇÐèÒªÔÚ marketing-cloud ¹æÔòÒýÇæ ÖгéÏó³öÒµÎñ·½ÓªÏú»î¶¯µÄ·µ»ØÐÅÏ¢£¬Í¬Ê±´òͨ¸öÐÔ»¯ÓªÏú»î¶¯Ó빫¹²½»Òס¢½áËã»·½Ú£¬ÐγÉÒ»¸öÍêÕûµÄÒµÎñÁ÷¡£

ÕâÊÇÒ»¸ö marketing-cloud Âß¼­¼Ü¹¹Í¼£¬¸úÎÒÃÇÖ÷ÌâÏà¹ØµÄ¾ÍÊÇ ÓªÏú¹æÔòÒýÇæ £¬Ëû¾ÍÊÇÎÒÃÇÕâÀïËù˵µÄºÏÀíµÄÒµÎñ³¡¾°¡£

ÔÚÕû¸öÕýÏòϵ¥¹ý³ÌÖУ¬ÓªÏú¹æÔòÒýÇæÒª¼ç¸ºÆð¼ÈÒªÌṩ marketing-cloud ÄڵĹ²ÓÃÓªÏú»î¶¯£¬»¹ÐèҪǎÓÍⲿӪÏúÖÐÐĵĸ÷ÀàÓªÏúÍæ·¨£¬ÍⲿµÄÓªÏúÖÐÐÄ»áÓжà¸ö£¬Ä¿Ç°ÎÒÃÇÖ÷ÒªÓÐÁ½¸ö¡£

ÓÉÓÚÕâÆªÎÄÕ²»ÊǽéÉÜÓªÏúƽ̨ÔõôÉè¼Æ£¬ËùÒÔÕâÀï²»´òËãÀ©Õ¹»°Ìâ¡£Ö÷ÒªÊÇÆðµ½Å×שÒýÓñµÄÄ¿µÄ£¬Æ½Ì¨Ð͵ÄÒµÎñ»á´æÔÚ¸÷ÖÖ¸÷ÑùµÄ¶ÔÍâϵͳÒÀÀµµÄÒµÎñ³¡¾°¡£ÎÄÕ½ÓÏÂÀ´µÄ²¿·Ö½«Õ¹¿ª marketing-cloud ¹æÔòÒýÇæ ÔÚ´òͨ²âÊÔÁ´Â·ÉϵÄʵ¼ù¡£

¿ª·¢½×¶Î unitTest mock ÍⲿÒÀÀµ

ÔÚ¿ª·¢½×¶Î£¬ÎÒÃǻᾭ³£ÐԵıàдµ¥Ôª²âÊÔÀ´²âÊÔÎÒÃǵÄÂß¼­£¬ÔÚ±àд unitTest µÄʱºò¶¼ÐèÒª mock ÖܱߵÄÒÀÀµ£¬mock ³öÀ´µÄ¶ÔÏó·ÖΪÁ½ÖÖÀàÐÍ£¬Ò»ÖÖÊDz»¾ßÓÐ Assert Âß¼­µÄ stub ×® ¶ÔÏ󣬻¹ÓÐÒ»ÖÖ¾ÍÊÇÐèÒªÖ§³Ö Assert µÄ mocker Ä£Äâ¶ÔÏó¡£

µ«ÊÇÎÒÃÇÒ²²»ÐèÒªÃ÷ÏÔÇø·ÖËûÃÇ£¬Á½ÕßµÄÇø±ð²»ÊÇÌ«Ã÷ÏÔ£¬ÔÚ±àÂë¹æ·¶ÄÚ¿ÉÄÜÐè񻂿·Ö¡£

ÎÒÃǹØÐĵÄÊÇÈçºÎ½â¾ö¶ÔÏóÖ®¼äµÄÒÀÀµÎÊÌ⣬¸÷ÖÖ mock ¿ò¼ÜÆäʵÌṩÁ˺ܶà·Ç³£ºÃÓõŤ¾ß£¬ÎÒÃÇ¿ÉÒÔºÜÇáËÉµÄ mock ÖܱߵÄÒÀÀµ¡£

given(marketingService.mixMarketingActivity
(anyObject()))
.willReturn(stubResponse);
RuleCalculateResponse response =
this.ruleCalculatorBiz.ruleCalculate(request);

ÕâÀïÎÒÃÇ mock ÁË marketingService.mixMarketingActivity() ·½·¨¡£

Java ÊÀ½çÀïÌṩÁ˺ܶàºÃÓÃµÄ mock ¿ò¼Ü£¬±È½ÏÁ÷ÐкÃÓõĿò¼ÜÖ®Ò» mockito ¿ÉÒÔÇáËÉ mock Service ²ãµÄÒÀÀµ£¬µ±È»³ýÁË mockito Ö®Í⻹ÓкܶàÓÅÐãµÄ mock ¿ò¼Ü¡£

ÕâЩ¿ò¼Ü´óͬСÒ죬±àд unitTest ×î´óµÄÎÊÌâ¾ÍÊÇÈçºÎÖØ¹¹Âß¼­Ê¹Ö®¸ü¼Ó±ãÓÚ²âÊÔ£¬Ò²¾ÍÊÇ´úÂëÊÇ·ñ¾ß±¸ºÜºÃµÄ¿É²âÊÔÐÔ£¬ÊÇ·ñÒѾ­Ïû³ýÁ˾ø´ó¶àÊý private ·½·¨£¬private ·½·¨ÊÇ·ñÓÐijЩָÔðÊÇÎÒÃÇûÓв¶×½µ½ÒµÎñ¸ÅÄî¡£

Á¬µ÷½×¶Î mock ÍⲿÒÀÀµ

ÔÚÎÒÃÇÍê³ÉÁËËùÓеĿª·¢£¬ÍêÉÆµÄµ¥Ôª²âÊÔ±£Ö¤ÁËÎÒÃÇÄÚ²¿µÄÂß¼­ÊÇûÓÐÎÊÌâµÄ£¨µ±È»ÕâÀï²»ÌÖÂÛ unitTest µÄ case µÄÉè¼ÆÊÇ·ñÍêÉÆÇé¿ö£©¡£

ÏÖÔÚÎÒÃÇÐèÒª¶Ô½ÓÖܱßϵͳ¿ª·¢½øÐÐÁ¬µ÷ÁË£¬Õâ¸öÖܱßϵͳ»¹ÊÇÊôÓÚ±¾Æ½Ì¨Ö®ÀàµÄÆäËûÖ§³Åϵͳ¡£±ÈÈçÎÒÃÇµÄ marketing-cloud ¹æÔòÒýÇæÏµÍ³ Óë ϵ¥ÏµÍ³ Ö®¼äµÄ¹ØÏµ¡£ÔÚ¿ª·¢µÄʱºòÎÒÃDZàд unitTest ÊÇ˳ÀûµÄÍê³ÉÁË¿ª·¢½â¾öµÄÑéÖ¤¹¤×÷£¬µ«ÊÇÏÖÔÚÃæ¶ÔÁ¬µ÷ÎÊÌâ¡£

ϵͳÐèÒªÕýʽµÄÅÜÆðÀ´£¬µ«ÊÇÎÒÃÇȱ·¦¶ÔÍⲿӪÏúÖÐÐĵÄÒÀÀµ£¬ÎÒÃÇÔõô°ì¡£ÆäʵÎÒÃÇÒ²ÐèÒªÔÚÁ¬µ÷½×¶Î mock ÍⲿÒÀÀµ£¬Ö»²»¹ýÕâ¸ö mock µÄ¼¼ÊõºÍ·½·¨²»ÊÇͨ¹ý unitTest ¿ò¼ÜÀ´Ö§³Ö£¬¶øÊÇÐèÒªÎÒÃÇ×Ô¼ºÀ´Éè¼ÆÎÒÃǵÄÕû¸ö·þÎñµÄ¿ª·¢¼Ü¹¹¡£

Ê×ÏÈÒªÄÜʶ±ð±¾´Î request ÊÇÐèÒª mock µÄ£¬ÄǾÍÐèҪijÖÖ mock parameter ²ÎÊýÀ´Ìṩʶ±ðÄÜÁ¦¡£

ÎÒÃÇÀ´¿´Ï marketing-cloud ÓªÏú¹æÔòÒýÇæ ÔÚÕâ¿éµÄÒ»¸ö³õ²½³¢ÊÔ¡£

public interface CCMarketingCentralFacade {
CallResponse callMarketingCentral(CallRequest request);
}

public interface ClassMarketingCentralFacade {
CallResponse callMarketingCentral(CallRequest request);
}

ÓªÏú¹æÔòÒýÇæÊ¹Óà RestEasy client api ×÷Ϊ rest µ÷Óÿò¼Ü¡£ÕâÁ½¸ö Facade ÊÇÓªÏúƽ̨¶Ô CCTalk ¡¢»¦½­ÍøÐ£ »¦½­Á½´ó×Ó¹«Ë¾ÓªÏúÖÐÐÄ·¢Æðµ÷ÓÃµÄ Facade¡£

(ΪÁ˾¡Á¿»¹Ô­ÎÒÃǵŤ³Ìʵ¼ù¸É»õͬʱÐèÒªÏû³ýһЩÃô¸ÐÐÅÏ¢µÄÇé¿öÏ£¬ÕûƪÎÄÕÂËùÓеĴúÂëʵÀý£¬ÎÒ¶¼É¾³ýÁËһЩ²»Ó°ÏìÔĶÁÇҺͱ¾ÎÄÎ޹صĴúÂ룬ͬʱ×öÁËһЩα±àÂëºÍÊ¡ÂÔ£¬Ê¹´úÂë¸ü¾«¼ò¸ü±ãÓÚÔĶÁ¡£)

ÔÚÕý³£Âß¼­Ï£¬ÎÒÃÇ»á¸ù¾ÝÓªÏú·ÓÉ key À´¾ö¶¨µ÷ÓÃÄĸö¹«Ë¾µÄÓªÏúÖÐÐĽӿڣ¬µ«ÊÇÓÉÓÚÎÒÃÇÔÚ¿ª·¢Õâ¸öÏîÄ¿µÄʱºòÔÝʱҵÎñ·½»¹Ã»ÓдæÔڵĵØÖ·ÈÃÎÒÃǶԽӣ¬ËùÒÔÎÒÃÇ×Ô¼º×öÁË mock facade£¬À´½â¾öÁ¬µ÷ÎÊÌâ¡£

public class CCMarketingCentralFacadeMocker implements CCMarketingCentralFacade {

@Override
public CallResponse callMarketingCentral(CallRequest request) {

CallResponse response = ...
MarketingResultDto marketingResultDto = ...
marketingResultDto.setTotalDiscount(new BigDecimal("90.19"));
marketingResultDto.setUseTotalDiscount(true);

response.getData().setMarketingResult
(marketingResultDto);

return response;
}
}

public class ClassMarketingCentralFacadeMocker implements ClassMarketingCentralFacade {

@Override
public CallResponse callMarketingCentral(CallRequest request) {
CallResponse response = ...

MarketingResultDto marketingResultDto = ...
marketingResultDto.setUseCoupon(true);
marketingResultDto.setTotalDiscount(null);
marketingResultDto.setUseTotalDiscount(false);

List<MarketingProductDiscountDto> discountDtos = ...

request.getMarketingProductTagsParameter().
getMarketingTags().forEach(item -> {

MarketingProductDiscountDto discountDto = ...
discountDto.setProductId(item.getProductID());
...
discountDtos.add(discountDto);
});
...
return response;
}
}

ÎÒÃǶ¨ÒåÁËÁ½¸ö mock À࣬¶¼ÊÇһЩ²âÊÔÊý¾Ý£¬¾ÍÊÇΪÁ˽â¾öÔÚÁ¬µ÷½×¶ÎµÄÎÊÌ⣬Ҳ¾ÍÊÇÔÚ DEV »·¾³ÉϵÄÒÀÀµÎÊÌâ¡£

ÓÐÁË mock facade Ö®ºó¾ÍÐèÒª request ¶¨Òå mock parameter ²ÎÊýÁË¡£

public abstract class BaseRequest implements Serializable {
public MockParameter mockParameter;
}

public class MockParameter {

/**
* mock cc ÓªÏúµ÷ÓýӿÚ
*/
public Boolean mockCCMarketingInterface;

/**
* mock class ÓªÏúµ÷ÓýӿÚ
*/
public Boolean mockClassMarketingInterface;

/**
* ÊÇ·ñ×Ô¶¯»¯²âÊÔ mock
*/
public Boolean useAutoTestMock;

/**
* ²âÊÔmock²ÎÊý
*/
public String testMockParam;

}

ÎÒÃÇÔÝÇÒºöÂÔͨÓÃÐÍÖ®ÀàµÄÉè¼Æ£¬ÕâÀïÖ»ÊÇÎÒÃÇÔÚ¸ÏÏîÄ¿µÄÇé¿öÏÂ×öµÄÒ»¸öµü´ú³¢ÊÔ£¬µÈÎÒÃǰÑÕâÕû¸öÁ÷³Ì¶¼ÅÜͨÁËÔÙÀ´¿¼ÂÇÖØ¹¹ÌáÈ¡¿ò¼Ü¡£

ÓÐÁËÊäÈë²ÎÊý£¬ÎÒÃǾͿÉÒÔ¸ù¾Ý²ÎÊýÅжÏÀ´¶¯Ì¬×¢Èë mock facade¡£

×Ô¶¯»¯²âÊÔ½×¶Î mock ÐèÇó

ÎÒÃǼÌÐøÏòÇ°ÍÆ½ø£¬¹ýÁËÁ¬µ÷½×¶Î½ô½ÓמͽøÈë²âÊÔ»·½Ú£¬ÏÖÔÚ»ù±¾ÉÏ´ó¶àÊý»¥ÁªÍø¹«Ë¾¶¼ÊÇ×Ô¶¯»¯µÄ²âÊÔ£¬ºÜÉÙÔÚÓÐÊÖ¶¯µÄ£¬ÓÈÆäÊǺó¶Ëϵͳ¡£

ÄÇôÔÚ autoTest ½×¶ÎÃæÁÙµÄÒ»¸öÎÊÌâ¾ÍÊÇ£¬ÎÒÃÇÐèÒªÒ»¸ö¹«¹²µÄ autoTest µØÖ·£¬Õâ¸ö²âÊÔµØÖ·ÊDz»±äµÄ£¬ÎÒÃÇÔÚ×Ô¶¯»¯²âÊÔÏ mock µÄ facade bean µÄµØÖ·¾ÍÊÇÕâ¸öµØÖ·£¬Õâ¸öµØÖ·Êä³öµÄÖµÐèÒªÄܹ»¶ÔÓ¦µ½Ã¿´Î×Ô¶¯»¯½Å±¾Ö´ÐеÄÉÏÏÂÎÄÖС£

ÎÒÃÇÓкܶà΢·þÎñϵͳÀ´×é³ÉÒ»¸öƽ̨£¬Ã¿¸ö·þÎñ¶¼ÓÐÒÀÀµµÄµÚÈý·½½Ó¿Ú£¬Ô­À´ÔÚ×Ô¶¯»¯²âÊÔÕâЩ·þÎñµÄʱºò¶¼ÐèҪȥÁ˽âÒµÎñ·½ÏµÍ³µÄ½Ó¿Ú¡¢DB¡¢Ç°Ì¨Èë¿ÚµÈ£¬ÒòΪÔÚ±àд×Ô¶¯»¯½Å±¾µÄʱºòÐèҪͬ²½´´½¨²âÊÔÊý¾Ý£¬×îºó²ÅÄÜ Assert¡£

Õâ¸ö¿ç²¿ÃŵŵͨºÍЭ×÷ЧÂÊÑÏÖØµÍÏ£¬¶øÇÒÈËÔ±±ä¶¯¡¢ÏµÍ³±ä¶¯¶¼»áÖ±½ÓÓ°ÏìÉÏÏßÖÜÆÚ£¬ÕâÀï¾ø¶ÔÖµµÃ´´ÐÂÀ´½â¾öÕâ¸öЧÂÊÑÏÖØ×èÈûÎÊÌâ¡£

@Value("${marketing.cloud.business.access.url.mock}")
private String mockUrl;

/**
* ×Ô¶¯»¯²âÊÔ mocker bean
*/
@Bean("CCMarketingCentralFacadeTestMock")
public CCMarketingCentralFacade CCMarketingCentralFacadeTestMock() {
RestClientProxyFactoryBean<CCMarketingCentralFacade> restClientProxyFactoryBean ...
restClientProxyFactoryBean.setBaseUri(this.mockUrl);
...
}

/**
* ×Ô¶¯»¯²âÊÔ mocker bean
*/
@Bean("ClassMarketingCentralFacadeTestMock")
public ClassMarketingCentralFacade ClassMarketingCentralFacadeTestMock() {
RestClientProxyFactoryBean<ClassMarketingCentralFacade> restClientProxyFactoryBean ...
restClientProxyFactoryBean.setBaseUri(this.mockUrl);
...
}

ÕâÀïµÄ mockUrl ¾ÍÊÇÎÒÃdzéÏó³öÀ´µÄͳһµÄ autoTest µØÖ·£¬ÔÚÇ°ÃæµÄ mock parameter ÖÐÓÐÒ»¸ö useAutoTestMock Boolean ÀàÐ͵IJÎÊý£¬Èç¹ûµ±Ç°ÇëÇó´Ë²ÎÊýΪ true£¬ÎÒÃǽ«¶¯Ì¬×¢Èë×Ô¶¯»¯²âÊÔ mock bean £¬ºóÐøµÄËùÓе÷Óö¼»á×ßµ½ mockUrl Ö¸¶¨µÄµØ·½¡£

autoTest Mock Gateway ¸¡³öË®Ãæ

µ½Ä¿Ç°ÎªÖ¹£¬ÎÒÃÇÓöµ½ÁË×Ô¶¯»¯²âÊÔͳһµÄ mock µØÖ·ÒªÊÕ¿ÚËùÓÐ΢·þÎñÔÚÕâ·½ÃæµÄÐèÇó¡£ÏÖÔÚ×î´óµÄÎÊÌâ¾ÍÊÇ£¬ËùÓеÄ΢·þÎñ¶ÔÍâÒÀÀµµÄ response ¶¼²»Ïàͬ£¬×Ô¶¯»¯½Å±¾ÔÚÖ´ÐеÄʱºòÔ¤ÏÈ´´½¨ºÃµÄ response ÒªÄÜÊÊÅäµ½µ±Ç°²âÊÔµÄÉÏÏÂÎÄÖС£

±ÈÈ磬ӪÏú¹æÔòÒýÇæ£¬ÎÒÃǵÄ×Ô¶¯»¯½Å±¾ÔÚ´´½¨Ò»¸ö¶©µ¥µÄʱºòÐèÒªÔ¤Ïȹ¹ÔìºÃµ±Ç°ÉÌÆ·£¨±ÈÈ磬productID£º101010£©£¬ÔÚ»ñÈ¡ÍⲿӪÏúÖÐÐÄÌṩµÄ»î¶¯ÐÅÏ¢ºÍµÖ¿ÛÐÅÏ¢µÄ response £¬×îºó²ÅÄÜÈ¥ Assert ¶©µ¥µÄ½ð¶îºÍ»î¶¯ÐÅÏ¢¼Ç¼ÊÇ·ñÕýÈ·£¬Õâ¾ÍÊÇÒ»´Î autoTest context ¡£

ÓÐÁ½ÖÖ·½Ê½À´Ê¶±ðµ±Ç° autoTest context £¬Ò»ÖÖÊÇÔÚ case Ö´ÐеÄʱºòÈ·¶¨ÉÌÆ·ID£¬×îºóͨ¹ýÉÌÆ·IDÀ´»ñÈ¡ mock µÄ response ¡£»¹ÓÐÒ»ÖÖ¾ÍÊÇÖ§³Ö´«µÝ autoTest mock ²ÎÊý¸øµ½ mockUrl Ö¸¶¨µÄ·þÎñ£¬¿ÉÒÔʹÓÃÕâ¸ö²ÎÊýÀ´Ê¶±ðµ±Ç°²âÊÔÉÏÏÂÎÄ¡£

Ò»¸ö²âÊÔ case ¿ÉÄܻᴩ¹ýºÜ¶à΢·þÎñ£¬ÕâЩËùÓеÄÒÀÀµ·þÎñ¿ÉÄܶ¼ÐèÒªÔ¤Éè mock response£¬Õâ»ù±¾ÉÏÊÇÒ»ÀÍÓÀÒݵġ£

ËùÒÔ£¬ÎÒÃdzéÏó³öÁË autoTest Mock Gateway£¨×Ô¶¯»¯²âÊÔmockÍø¹Ø·þÎñ£© £¬ÔÚÕû¸ö×Ô¶¯»¯²âÊÔ»·½Ú»¹ÓкܶàÐèÒªÖ§³ÖµÄ¹¤×÷£¬·þÎñÖ®¼äµÄ¼øÈ¨£¬¼øÈ¨ key µÄ mock£¬¼Ó½âÃÜ£¬¼Ó½âÃÜ key µÄ mock£¬×Ô¶¯»¯²âÊÔ case ½»Ìæ²¢ÐÐÖ´Ðеȡ£

×÷Ϊ¹¤³ÌʦµÄÎÒÃǶ¼Ï£ÍûÓÃϵͳ»¯¡¢¹¤³Ì»¯µÄ·½Ê½À´½â¾öÕûÌåÎÊÌ⣬¶ø²»ÊǸö±ðµã×´ÎÊÌâ¡£ÓÐÁËÕâ¸ö mock gateway ÎÒÃÇ¿ÉÒÔ×öºÜ¶àÊÂÇ飬Ҳ¿ÉÒÔÆÕ»ÝËùÓÐÐèÒªµÄÆäËû²¿ÃÅ¡£

ÔÚÒ»´Î autoTest context Àï¹¹ÔìºÃ mock response£¬È»ºóͨ¹ý mock parameter À´¶¯Ì¬Ê¶±ð¾ßÌåµÄÀ´Ô´·þÎñ½øÐзÓÉ¡¢¼øÈ¨¡¢¼Ó½âÃܵȲÙ×÷¡£

MockGateway ÊÇÒ»¸öÖ§µã£¬ÎÒÏàÐÅÕâ¸öÖ§µã¿ÉÒÔÇ˶¯ºÜ¶à²âÊÔ¿Õ¼äºÍ´´ÐÂÄÜÁ¦¡£

ÇáÁ¿¼¶°æ±¾ÊµÏÖ

½ÓÏÂÀ´ÎÒÃǽ«Õ¹Ê¾ÔÚ marketing-cloud ÓªÏú¹æÔòÒýÇæ Öеijõ²½³¢ÊÔ¡£

ÕûÌåÂß¼­¼Ü¹¹

×Ô¶¯»¯½Å±¾ÔÚÿÅÜÒ»¸ö case µÄʱºò»á´´½¨µ±Ç° case ¶ÔÓ¦µÄ autoTestContext£¬ÕâÀïÃæ¶¼ÊÇһЩ meta data£¬ÓÃÀ´±íʾÕâ¸ö case ÖÐËùÓÐÉæ¼°µ½µÄ΢·þÎñϵͳÄÄЩÊÇÐèÒª×ß mock gateway µÄ¡£

ÔÚ mockGateway ÖÐËùÓеÄÅäÖö¼ÊÇÓÐÒ»¸ö autoTestContext Ëù¶ÔÓ¦£¬Èç¹ûûÓÐ autoTestContext ˵Ã÷ÊÇËùÓÐ case ¹²Óá£

½« mock parameter ÄÉÈë·þÎñ¿ò¼Ü±ê×¼ request contract

ÒªÏë´òͨÕû¸ö΢·þÎñ¼Ü¹¹ÖеÄËùÓÐͨµÀ£¬¾ÍÐèÒªÔÚ±ê×¼ request contract ¶¨Òå mockParameter £¬ÕâÊÇÕâÒ»ÇеÄǰÌá¡£

·þÎñÓë·þÎñÖ®¼äµ÷ÓÃ×ß±ê׼΢·þÎñ request contract£¬·þÎñÓëÍⲿϵͳµÄÒÀÀµ¿ÉÒÔÑ¡Ôñ×ß HTTP Header£¬Ò²¿ÉÒÔÑ¡Ôñ×ß±ê×¼ request £¬¾ÍÒª¿´ÎÒÃǵÄÕû¸ö·þÎñ¿ò¼ÜÊÇ·ñÒѾ­¸²¸ÇËùÓеIJúÏß¼°Ò»Ð©ÒÅÁôϵͳµÄÎÊÌâ¡£

public abstract class BaseRequest implements Serializable {
public MockParameter mockParameter;
}

BaseRequest ÊÇËùÓÐ request µÄ»ùÀ࣬ÕâÑù²ÅÄܱ£Ö¤ËùÓеÄÇëÇóÄܹ»Õý³£µÄ´«µÝ¡£

ʹÓà AOP + RestEasy HttpClientRequest SPI ³õ²½ÊµÏÖ Mock

Õû¸öϵͳµÄ¿ª·¢¼Ü¹¹·Ö²ãÒÀÀµÊÇ£ºfacade->biz->service£¬»ù±¾µÄËùÓкËÐÄÂß¼­¶¼ÊÇÔÚ service ÖУ¬ÇëÇóµÄ request dto ×î¶à²»ÄÜÔ½½çµ½ service ²ã£¬°´Õչ淶½² request dto ¶¥¶àÖÍÁôÔÚ biz ²ã£¬µ«ÊÇÔÚ»¥ÁªÍøµÄÊÀ½çÖÐһЩ¶¼ÊÇ¿ÉÒÔ¿ìËÙµü´úµÄ£¬²¢²»ÊǶàôӲÐԹ涨£¬¼°Ê±Öع¹Êdz¥»¹¼¼ÊõÕ®ÎñµÄÖ÷Òª·½·¨¡£

Ç°ÃæÎÒÃÇÒѾ­½²¹ý£¬ÎÒÃDzÉÓÃµÄ RPC ¿ò¼ÜÊÇ RestEasy + RestEasy client £¬ÎÒÃÇÏÈÀ´¿´ÏÂÈë¿ÚµÄµØ·½¡£

@Component
@Path("v1/calculator/")
public class RuleCalculatorFacadeImpl extends BaseFacade implements RuleCalculatorFacade {
@MockFacade(Setting = MockFacade.SETTING_REQUEST_MOCK_PARAMETER)
public RuleCalculateResponse ruleCalculate(RuleCalculateRequest request) {
...
}
}

ÔÙ¿´ÏÂ service ¶ÔÏó¡£

@Component
public class MarketingServiceImpl extends MarketingBaseService implements MarketingService {
@MockFacade(Setting = MockFacade.SETTING_FACADE_MOCK_BEAN)
public MarketingResult onlyExtendMarketingActivity(Marketing..Parameter tagsParameter) {
...
}

ÎÒÃÇÖØµã¿´Ï @MockFacade annotation ÉùÃ÷¡£

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MockFacade {
String SETTING_REQUEST_MOCK_PARAMETER = "setting_request_mock_parameter";
String SETTING_FACADE_MOCK_BEAN = "setting_facade_mock_bean";

String Setting();
}

ͨ¹ýÕâ¸ö annotation ÎÒÃǵÄÖ÷ҪĿµÄ¾ÍÊǽ« mockParameter ·Åµ½ ThreadLocal ÖÐÈ¥ºÍÇëÇó´¦ÀíÍêʱµÄÇåÀí¹¤×÷¡£»¹ÓÐÒ»¸ö¹¦ÄܾÍÊÇ service ²ãµÄ mock bean ´¦Àí¡£

@Aspect
@Component
@Slf4j
public class MockMarketingFacadeInterceptor {

@Before("@annotation(mockFacade)")
public void beforeMethod(JoinPoint joinPoint,
MockFacade mockFacade) {

String settingName = mockFacade.Setting();

if (MockFacade.SETTING_REQUEST_MOCK_PARAMETER.
equals(settingName)) {

Object[] args = joinPoint.getArgs();
if (args == null) return;

List<Object> argList = Arrays.asList(args);
argList.forEach(item -> {

if (item instanceof BaseRequest) {
BaseRequest request = (BaseRequest) item;

if (request.getMockParameter() != null) {
MarketingBaseService.mockParameterThreadLocal.set
(request.getMockParameter());
log.info("----setting mock parameter:{}", JSON.toJSONString(request.getMockParameter()));
}
}
});
} else if (MockFacade.SETTING_FACADE_MOCK_BEAN
.equals(settingName)) {

MarketingBaseService marketingBaseService
= (MarketingBaseService) joinPoint.getThis();
marketingBaseService.mockBean();
log.info("----setting mock bean.");
}
}

@After("@annotation(mockFacade)")
public void afterMethod(JoinPoint joinpoint,
MockFacade mockFacade) {

if (MockFacade.SETTING_FACADE_MOCK_BEAN.equals
(mockFacade.Setting())) {

MarketingBaseService marketingBaseService
= (MarketingBaseService) joinpoint.getThis();
marketingBaseService.mockRemove();

log.info("----remove mock bean.");
}

if (MockFacade.SETTING_REQUEST_MOCK_PARAMETER
.equals(mockFacade.Setting())) {

MarketingBaseService.mockParameterThreadLocal.remove();

log.info("----remove ThreadLocal. ThreadLocal get {}", MarketingBaseService.mockParameterThreadLocal.get());
}
}
}

ÕâЩÂß¼­ÍêÈ«»ùÓÚÒ»¸öÔ¼¶¨£¬¾ÍÊÇ MarketingBaseService£¬²»¾ßÓÐͨÓÃÐÍ£¬Ö»ÊÇÔÚÖð²½µÄÖØ¹¹ºÍÌáÈ¡ÖУ¬×îÖÕ»áÊÇÒ»¸ö plugin ¿ò¼Ü¡£

public abstract class MarketingBaseService
extends BaseService {

protected ClassMarketingCentralFacade classMarketingCentralFacade;

protected CCMarketingCentralFacade
ccMarketingCentralFacade;

public static ThreadLocal<MockParameter>
mockParameterThreadLocal = new ThreadLocal<>();

public void mockBean() {

MockParameter mockParameter =
mockParameterThreadLocal.get();

if (mockParameter != null && mockParameter.mockClassMarketingInterface) {
if (mockParameter.useAutoTestingMock) {
this.setClassMarketingCentralFacade
(SpringContextHolder.getBean
("ClassMarketingCentralFacadeTestMock", ClassMarketingCentralFacade.class));
} else {
this.setClassMarketingCentralFacade
(SpringContextHolder.getBean
("ClassMarketingCentralFacadeMocker", ClassMarketingCentralFacadeMocker.class));
}
} else {
this.setClassMarketingCentralFacade
(SpringContextHolder.getBean
("ClassMarketingCentralFacade", ClassMarketingCentralFacade.class));
}

if (mockParameter != null && mockParameter.mockCCMarketingInterface) {
if (mockParameter.useAutoTestingMock) {
this.setCcMarketingCentralFacade
(SpringContextHolder.getBean
("CCMarketingCentralFacadeTestMock", CCMarketingCentralFacade.class));
} else {
this.setCcMarketingCentralFacade
(SpringContextHolder.getBean
("CCMarketingCentralFacadeMocker", CCMarketingCentralFacadeMocker.class));
}
} else {
this.setCcMarketingCentralFacade
(SpringContextHolder.getBean
("CCMarketingCentralFacade",
CCMarketingCentralFacade.class));
}
}

public void mockRemove() {
mockParameterThreadLocal.remove();
}
}

ÎÒÃÇ¿ÉÒÔ˳ÀûµÄ½« request ÖÐµÄ mockParameter ·Åµ½ ThreadLocal ÖУ¬¿ÉÒÔ¶¯Ì¬µÄͨ¹ý AOP µÄ·½Ê½À´×¢ÈëÏàÓ¦µÄ mockerBean¡£

ÏÖÔÚÎÒÃÇ»¹Òª´¦ÀíµÄ¾ÍÊÇ¶Ô mockGateway µÄµ÷Óý« _mockParameter ÖÐµÄ autoContext Öеıêʾ×Ö·û´®·Åµ½ HTTP Header ÖÐÈ¥¡£

@Component
public class MockHttpHeadSetting implements ClientRequestFilter {

@Override
public void filter(ClientRequestContext requestContext) throws IOException {

MultivaluedMap<String, Object> header = requestContext.getHeaders();

MockParameter mockParameter = MarketingBaseService.mockParameterThreadLocal.get();

if (mockParameter != null && StringUtils.isNotBlank(mockParameter
.getTestingMockParam())) {
header.add("Mock-parameter", mockParameter.getTestingMockParam());
}
}
}

½Ó×ÅÔÚ SPI£¨javax.ws.rs.ext.Providers £© ÎļþÖÐÅäÖü´¿É

com.hujiang.marketingcloud.ruleengine
.service.MockHttpHeadSetting

×ܽá

ÔÚÕû¸ö΢·þÎñ¼Ü¹¹µÄʵ¼ùÖУ¬¹¤³Ì½çһֱȱÉÙ̽ÌֵľÍÊÇÔÚ΢·þÎñ¼Ü¹¹µÄ²âÊÔÕâ¿é£¬ÀëÎÒÃDZȽϽüµÄÊÇ×Ô¶¯»¯²âÊÔ£¬ÒòΪ×Ô¶¯»¯²âÊÔ»ù±¾ÉÏÊÇËùÓÐϵͳ¶¼ÐèÒªµÄ¡£

µ«ÊÇÓÐÒ»¿éÎÒÃÇһֱûÓÐÖØÊӵľÍÊÇ È«Á´Â·Ñ¹Á¦²âÊÔ Õâ¿é£¬ÔÚÉú²úÉϽøÐÐÈ«Á´Â·µÄÕæÊµµÄѹÁ¦²âÊÔÐèÒª½â¾öºÜ¶àÎÊÌ⣬±È½ÏÖØÒªµÄ¾ÍÊÇ DB Õâ¿é£¬Ñ¹²âµÄʱºò²úÉúµÄËùÓн»Ò×Êý¾Ý²»Äܹ»²ÎÓë½áËã¡¢²ÆÎñÁ÷³Ì£¬Õâ¾ÍÐèÒª½èÖú Ó°×Ó±í À´½â¾ö£¬ËùÓеÄÊý¾Ý¶¼²»»áдÈë×îÖÕµÄÕæÊµµÄ½»Ò×Êý¾ÝÖÐÈ¥¡£µ±È»»¹ÓÐÆäËûµØ·½¶¼ÐèÒª½â¾ö£¬Ò»µ©´ò¿ªÈ«Á´Â·Ñ¹²â¿ª¹Ø£¬Ó¦¸ÃÐèÒª´¦ÀíËùÓвúÉúÊý¾ÝµÄµØ·½£¬ÕâÊÇÒ»¸öÅÓ´óµÄ¹¤³Ì£¬µ«ÊÇÒ²»á·Ç³£ÓÐÒâ˼¡£

±¾ÆªÎÄÕÂÖ»ÊÇÎÒÃÇÔÚÕâ¿éµÄÒ»¸ö³õ²½³¢ÊÔ£¬ÎÒÃÇ»á¼ÌÐøÀ©Õ¹ÏÂÈ¥£¬ÔÚÏ´βúÏßÈ«Á´Â·Ñ¹²âµÄʱºòÎÒÃǾͿÉÒÔ½èÖúÏÖÔÚµÄʵ¼ù¼Ü¹¹À©Õ¹ÆðÀ´¡£

   
5616 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

΢·þÎñ²âÊÔÖ®µ¥Ôª²âÊÔ
һƪͼÎÄ´øÄãÁ˽â°×ºÐ²âÊÔÓÃÀýÉè¼Æ·½·¨
È«ÃæµÄÖÊÁ¿±£ÕÏÌåϵ֮»Ø¹é²âÊÔ²ßÂÔ
È˹¤ÖÇÄÜ×Ô¶¯»¯²âÊÔ̽Ë÷
Ïà¹ØÎĵµ

×Ô¶¯»¯½Ó¿Ú²âÊÔʵ¼ù֮·
jenkins³ÖÐø¼¯³É²âÊÔ
ÐÔÄܲâÊÔÕï¶Ï·ÖÎöÓëÓÅ»¯
ÐÔÄܲâÊÔʵÀý
Ïà¹Ø¿Î³Ì

³ÖÐø¼¯³É²âÊÔ×î¼Ñʵ¼ù
×Ô¶¯»¯²âÊÔÌåϵ½¨ÉèÓë×î¼Ñʵ¼ù
²âÊԼܹ¹µÄ¹¹½¨ÓëÓ¦ÓÃʵ¼ù
DevOpsʱ´úµÄ²âÊÔ¼¼ÊõÓë×î¼Ñʵ¼ù