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

1Ôª 10Ôª 50Ôª





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



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
ÉîÈëÀí½âJUnit 5µÄÀ©Õ¹Ä£ÐÍ
 
  3440  次浏览      27
 2018-9-4 
 

 

±à¼­ÍƼö:
±¾ÎÄÀ´×ÔÓÚinfoq£¬JUnitÊÇ×îÊÜ»¶Ó­µÄ»ùÓÚJVMµÄ²âÊÔ¿ò¼Ü£¬ÔÚµÚ5¸öÖ÷Òª°æ±¾ÖнøÐÐÁ˳¹µ×µÄ¸ÄÔì¡£

¹Ø¼üÒªµã

JUnit 5ÊÇÒ»¸öÄ£¿é»¯ºÍ¿ÉÀ©Õ¹µÄ²âÊÔ¿ò¼Ü£¬Ö§³ÖJava 8¼°¸ü¸ß°æ±¾¡£

JUnit 5ÓÉÈý¸ö²¿·Ö×é³É¡ª¡ªÒ»¸ö»ù´¡Æ½Ì¨¡¢Ò»¸öеıà³ÌºÍÀ©Õ¹Ä£ÐÍJupiter£¬ÒÔ¼°Ò»¸öÃûΪVintageµÄÏòºó¼æÈݵIJâÊÔÒýÇæ¡£

JUnit 5 JupiterµÄÀ©Õ¹Ä£ÐÍ¿ÉÓÃÓÚÏòJUnitÖÐÌí¼Ó×Ô¶¨Ò幦ÄÜ¡£

À©Õ¹Ä£ÐÍAPI²âÊÔÉúÃüÖÜÆÚÌṩÁ˹³×ÓºÍ×¢Èë×Ô¶¨Òå²ÎÊýµÄ·½·¨£¨¼´ÒÀÀµ×¢È룩¡£

JUnit 5ÌṩÁ˷ḻµÄ¹¦ÄÜ¡ª¡ª´Ó¸Ä½øµÄ×¢½â¡¢±êÇ©ºÍ¹ýÂËÆ÷µ½Ìõ¼þÖ´ÐкͶԶÏÑÔÏûÏ¢µÄ¶èÐÔÇóÖµ¡£ÕâÈûùÓÚTDD±àдµ¥Ôª²âÊÔ±äµÃÇá¶øÒ×¾Ù¡£Ð¿ò¼Ü»¹´øÀ´ÁËÒ»¸öÇ¿´óµÄÀ©Õ¹Ä£ÐÍ¡£À©Õ¹¿ª·¢ÈËÔ±¿ÉÒÔʹÓÃÕâ¸öÐÂÄ£ÐÍÏòJUnit 5ÖÐÌí¼Ó×Ô¶¨Ò幦ÄÜ¡£±¾ÎĽ«Ö¸µ¼ÄãÍê³É×Ô¶¨ÒåÀ©Õ¹µÄÉè¼ÆºÍʵÏÖ¡£ÕâÖÖ×Ô¶¨ÒåÀ©Õ¹»úÖÆÎªJava³ÌÐòÔ±ÌṩÁËÒ»ÖÖ´´½¨ºÍÖ´ÐйÊʺÍÐÐΪ£¨¼´BDD¹æ·¶²âÊÔ£©µÄ·½·¨¡£

ÎÒÃÇÊ×ÏÈʹÓÃJUnit 5ºÍÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹£¨³ÆÎª¡°StoryExtension¡±£©À´±àдһ¸öʾÀý¹ÊʺÍÐÐΪ£¨²âÊÔ·½·¨£©¡£Õâ¸öʾÀýʹÓÃÁËÁ½¸öеÄ×Ô¶¨Òå×¢½â¡°@Story¡±ºÍ¡°@Scenario¡±£¬ÒÔ¼°¡°Scene¡±À࣬ÓÃÒÔÖ§³ÖÎÒÃǵÄ×Ô¶¨ÒåStoryExtension£º

import org.junit.jupiter.api.extension.ExtendWith;

import ud.junit.bdd.ext.Scenario;
import ud.junit.bdd.ext.Scene;
import ud.junit.bdd.ext.Story;
import ud.junit.bdd.ext.StoryExtension;

@ExtendWith(StoryExtension.class)
@Story(name=¡°Returns go back to the stockpile¡±, description=¡°...¡°)
public class StoreFrontTest {

@Scenario(¡°Refunded items should be returned to the stockpile¡±)
public void refundedItemsShouldBeRestocked(Scene scene) {
scene
.given(¡°customer bought a blue sweater¡±,
() -> buySweater(scene, ¡°blue¡±))

.and(¡°I have three blue sweaters in stock¡±,
() -> assertEquals(3, sweaterCount(scene, ¡°blue¡±),
¡°Store should carry 3 blue sweaters¡±))

.when(¡°the customer returns the blue sweater for a refund¡±,
() -> refund(scene, 1, ¡°blue¡±))

.then(¡°I should have four blue sweaters in stock¡±,
() -> assertEquals(4, sweaterCount(scene, ¡°blue¡±),
¡°Store should carry 4 blue sweaters¡±))
.run();
}
}

 

´Ó´úÂëÆ¬¶ÎÖÐÎÒÃÇ¿ÉÒÔ¿´µ½£¬JupiterµÄÀ©Õ¹Ä£Ðͷdz£Ç¿´ó¡£ÎÒÃÇ»¹¿ÉÒÔ¿´µ½£¬ÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹¼°ÆäÏàÓ¦µÄ×¢½âΪ²âÊÔÓÃÀý±àдÕßÌṩÁ˼òµ¥¶ø¸É¾»µÄ·½·¨À´±àдBDD¹æ·¶¡£

×÷Ϊ¶îÍâµÄ½±Àø£¬µ±Ê¹ÓÃÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹³ÌÐòÖ´ÐвâÊÔʱ£¬»áÉú³ÉÈçÏÂËùʾµÄÎı¾±¨¸æ£º

STORY: Returns go back to the stockpile

As a store owner, in order to keep track of stock, I want to add items back to stock when they¡¯re returned.

SCENARIO: Refunded items should be returned to stock
GIVEN that a customer previously bought a blue sweater from me
AND I have three blue sweaters in stock
WHEN the customer returns the blue sweater for a refund
THEN I should have four blue sweaters in stock

 

ÕâЩ±¨¸æ¿ÉÒÔ×÷ΪӦÓóÌÐò¹¦Äܼ¯µÄÎĵµ¡£

×Ô¶¨ÒåÀ©Õ¹StoryExtensionÄܹ»½èÖúÒÔϺËÐĸÅÄîÀ´Ö§³ÖºÍÖ´ÐйÊʺÍÐÐΪ£º

ÓÃÓÚ×°ÊβâÊÔÀàºÍ²âÊÔ·½·¨µÄ×¢½â

JUnit 5 JupiterµÄÉúÃüÖÜÆÚ»Øµ÷

¶¯Ì¬²ÎÊý½âÎö

×¢½â

ʾÀýÖеġ°@ExtendWith¡±×¢½âÊÇÓÉJupiterÌṩµÄ±ê¼Ç½Ó¿Ú¡£ÕâÊÇÔÚ²âÊÔÀà»ò·½·¨ÉÏ×¢²á×Ô¶¨ÒåÀ©Õ¹µÄ·½·¨£¬Ä¿µÄÊÇÈÃJupiter²âÊÔÒýÇæµ÷Óøø¶¨Àà»ò·½·¨µÄ×Ô¶¨ÒåÀ©Õ¹¡£»òÕߣ¬²âÊÔÓÃÀý±àдÕß¿ÉÒÔͨ¹ý±à³ÌµÄ·½Ê½×¢²á×Ô¶¨ÒåÀ©Õ¹£¬»òÕßͨ¹ý·þÎñ¼ÓÔØÆ÷»úÖÆ½øÐÐ×Ô¶¯×¢²á¡£

ÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹ÐèÒªÒ»ÖÖʶ±ð¹ÊÊµķ½·¨¡£Îª´Ë£¬ÎÒÃǶ¨ÒåÁËÒ»¸öÃûΪ¡°Story¡±µÄ×Ô¶¨Òå×¢½âÀ࣬ÈçÏÂËùʾ£º

import org.junit.platform.commons.annotation.Testable;

@Testable
public @interface Story {...}

 

²âÊÔÓÃÀý±àдÕßÓ¦¸ÃʹÓÃÕâ¸ö×Ô¶¨Òå×¢½â½«²âÊÔÀà±ê¼ÇΪ¹ÊÊ¡£Çë×¢Ò⣬Õâ¸ö×¢½â±¾ÉíʹÓÃÁËJUnit 5ÄÚÖõġ°@Testable¡±×¢½â¡£Õâ¸ö×¢½âΪIDEºÍÆäËû¹¤¾ßÌṩÁËÒ»ÖÖʶ±ð¿É²âÊÔµÄÀàºÍ·½·¨µÄ·½Ê½¡ª¡ªÒ²¾ÍÊÇ˵£¬´øÓÐÕâ¸ö×¢½âµÄÀà»ò·½·¨¿ÉÒÔͨ¹ýJUnit 5 Jupiter²âÊÔÒýÇæÀ´Ö´ÐС£

ÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹»¹ÐèÒªÒ»ÖÖ·½·¨À´Ê¶±ð¹ÊÊÂÖеÄÐÐΪ»ò³¡¾°¡£Îª´Ë£¬ÎÒÃǶ¨ÒåÒ»¸öÃûΪ¡°Scenario¡±µÄ×Ô¶¨Òå×¢½âÀ࣬¿´ÆðÀ´ÏñÕâÑù£º

import org.junit.jupiter.api.Test;

@Test
public @interface Scenario {...}

 

²âÊÔÓÃÀý±àдÕßӦʹÓÃÕâ¸ö×Ô¶¨Òå×¢½â½«²âÊÔ·½·¨±ê¼ÇΪ³¡¾°¡£Õâ¸ö×¢½â±¾ÉíʹÓÃÁËJUnit 5 JupiterµÄÄÚÖá°@Test¡±×¢½â¡£µ±IDEºÍ²âÊÔÒýÇæÉ¨Ãè¸ø¶¨µÄÒ»×é²âÊÔÀಢÔÚ¹«¹²ÊµÀý·½·¨ÉÏÕÒµ½@Scenario×¢½âʱ£¬¾Í»á½«ÕâЩ·½·¨±ê¼ÇΪ¿ÉÖ´ÐеIJâÊÔ·½·¨¡£

Çë×¢Ò⣬ÓëJUnit 4µÄ@Test×¢½â²»Í¬£¬JupiterµÄ@Test×¢½â²»Ö§³Ö¿ÉÑ¡µÄ¡°Ô¤ÆÚ¡±Òì³£ºÍ¡°³¬Ê±¡±²ÎÊý¡£JupiterµÄ@Test×¢½âÊÇ´ÓÍ·¿ªÊ¼Éè¼ÆµÄ£¬²¢¿¼Âǵ½ÁË¿ÉÀ©Õ¹ÐÔ¡£

ÉúÃüÖÜÆÚ

JUnit 5 JupiterÌṩÁËÀ©Õ¹»Øµ÷£¬¿ÉÓÃÓÚ·ÃÎʲâÊÔÉúÃüÖÜÆÚʼþ¡£À©Õ¹Ä£ÐÍÌṩÁ˼¸¸ö½Ó¿Ú£¬ÓÃÓÚÔÚ²âÊÔÖ´ÐÐÉúÃüÖÜÆÚµÄ¸÷¸öʱ¼äµã¶Ô²âÊÔ½øÐÐÀ©Õ¹£º

À©Õ¹¿ª·¢Õß¿ÉÒÔ×ÔÓɵØÊµÏÖËùÓлò²¿·ÖÉúÃüÖÜÆÚ½Ó¿Ú¡£

¡°BeforeAllCallback¡±½Ó¿ÚÌṩÁËÒ»ÖÖ·½·¨ÓÃÓÚ³õʼ»¯À©Õ¹²¢ÔÚµ÷ÓÃJUnit²âÊÔÈÝÆ÷ÖеIJâÊÔÓÃÀý֮ǰÌí¼Ó×Ô¶¨ÒåÂß¼­¡£ÎÒÃǵÄStoryExtensionÀཫʵÏÖÕâ¸ö½Ó¿Ú£¬ÒÔÈ·±£¸ø¶¨µÄ²âÊÔÀàʹÓÃÁË¡°@Story¡±×¢½â¡£

import org.junit.jupiter.api.extension.BeforeAllCallback;

public class StoryExtension implements BeforeAllCallback {
@Override
public void beforeAll(ExtensionContext context) throws Exception {

if (!AnnotationSupport
.isAnnotated(context.getRequiredTestClass(), Story.class)) {
throw new Exception(¡°Use @Story annotation...¡°);
}
}
}

 

JupiterÒýÇæ½«Ìṩһ¸öÓÃÓÚÔËÐÐÀ©Õ¹µÄÖ´ÐÐÉÏÏÂÎÄ¡£ÎÒÃÇʹÓÃÕâ¸öÉÏÏÂÎÄÀ´È·¶¨ÕýÔÚÖ´ÐеIJâÊÔÀàÊÇ·ñʹÓÃÁË¡°@Story¡±×¢½â¡£ÎÒÃÇʹÓÃJUnitƽ̨ÌṩµÄAnnotationSupport¸¨ÖúÀàÀ´¼ì²éÊÇ·ñ´æÔÚÕâ¸ö×¢½â¡£

»ØÏëһϣ¬ÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹ÔÚÖ´ÐвâÊÔºó»áÉú³ÉBDD±¨¸æ¡£ÕâЩ±¨¸æµÄijЩ²¿·ÖÊÇ´Ó¡°@Store¡±×¢½âµÄÔªËØÖÐÌáÈ¡µÄ¡£ÎÒÃÇʹÓÃbeforeAll»Øµ÷À´±£´æÕâЩ×Ö·û´®¡£ÉÔºó£¬ÔÚÖ´ÐÐÉúÃüÖÜÆÚ½áÊøÊ±£¬ÔÙ»ùÓÚÕâЩ×Ö·û´®Éú³É±¨¸æ¡£ÎÒÃÇʹÓÃÁËÒ»¸ö¼òµ¥µÄPOJO¡£ÎÒÃǽ«Õâ¸öÀàÃüÃûΪ¡°StoryDe??tails¡±¡£ÒÔÏ´úÂëÆ¬¶ÎÑÝʾÁË´´½¨Õâ¸öÀàʵÀýµÄ¹ý³Ì£¬²¢½«×¢½âÔªËØ±£´æµ½ÊµÀýÖУº

public class StoryExtension implements BeforeAllCallback {
@Override
public void beforeAll(ExtensionContext context) throws Exception {

Class<?> clazz = context.getRequiredTestClass();
Story story = clazz.getAnnotation(Story.class);

StoryDetails storyDetails = new StoryDetails()
.setName(story.name())
.setDescription(story.description())
.setClassName(clazz.getName());

context.getStore(NAMESPACE).put(clazz.getName(), storyDetails);
}
}

 

ÎÒÃÇÐèÒª½âÊÍһϷ½·¨µÄ×îºóÒ»¸öÓï¾ä¡£ÎÒÃÇʵ¼ÊÉÏÊÇ´ÓÖ´ÐÐÉÏÏÂÎÄÖлñȡһ¸ö´øÓÐÃû×ֵĴ洢£¬²¢½«Ð´´½¨µÄ¡°StoryDe??tails¡±ÊµÀý±£´æµ½Õâ¸ö´æ´¢ÖС£

×Ô¶¨ÒåÀ©Õ¹¿ÉÒÔʹÓô洢À´±£´æºÍ»ñÈ¡ÈÎÒâÊý¾Ý¡ª¡ª»ù±¾ÉϾÍÊÇÒ»¸ö´æÔÚÓÚÄÚ´æÖеÄmap¡£ÎªÁ˱ÜÃâ¶à¸öÀ©Õ¹Ö®¼ä³öÏÖÒâÍâµÄkey³åÍ»£¬JUnitÒýÈëÁËÃüÃû¿Õ¼äµÄ¸ÅÄî¡£ÃüÃû¿Õ¼äÊÇÒ»ÖÖ¶Ô²»Í¬À©Õ¹±£´æµÄÊý¾Ý½øÐиôÀëµÄ·½·¨¡£ÓÃÓÚ¸ôÀëÀ©Õ¹Êý¾ÝµÄÒ»ÖÖ³£Ó÷½·¨ÊÇʹÓÃ×Ô¶¨ÒåÀ©Õ¹ÀàÃû£º

private static final Namespace NAMESPACE = Namespace
.create(StoryExtension.class);

 

ÎÒÃǵÄÀ©Õ¹ÐèÒªÓõ½µÄÁíÒ»¸ö×Ô¶¨Òå×¢½âÊÇ¡°@Scenario¡±×¢½â¡£Õâ¸ö×¢½âÓÃÓÚ½«²âÊÔ·½·¨±ê¼ÇΪ¹ÊÊÂÖеij¡¾°»òÐÐΪ¡£ÎÒÃǵÄÀ©Õ¹½«½âÎöÕâЩ³¡¾°£¬ÒԱ㽫ËüÃÇ×÷ΪJUnit²âÊÔÓÃÀýÀ´Ö´Ðв¢Éú³É±¨¸æ¡£»ØÏëÒ»ÏÂÎÒÃÇ֮ǰ¿´µ½µÄÉúÃüÖÜÆÚͼÖеġ°BeforeEachCallback¡±½Ó¿Ú£¬ÔÚµ÷ÓÃÿ¸ö²âÊÔ·½·¨Ö®Ç°£¬ÎÒÃǽ«Ê¹Óûص÷À´Ìí¼Ó¸½¼ÓÂß¼­£º

import org.junit.jupiter.api.extension.BeforeEachCallback;

public class StoryExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) throws Exception {
if (!AnnotationSupport.
isAnnotated(context.getRequiredTestMethod(), Scenario.class)) {
throw new Exception(¡°Use @Scenario annotation...¡°);
}
}
}

 

ÈçǰËùÊö£¬JupiterÒýÇæ½«Ìṩһ¸öÓÃÓÚÔËÐÐÀ©Õ¹µÄÖ´ÐÐÉÏÏÂÎÄ¡£ÎÒÃÇʹÓÃÉÏÏÂÎÄÀ´È·¶¨ÕýÔÚÖ´ÐеIJâÊÔ·½·¨ÊÇ·ñʹÓÃÁË¡°@Scenario¡±×¢½â¡£

»Øµ½±¾ÎĵĿªÍ·£¬ÎÒÃÇÌṩÁËÒ»¸ö¹ÊʵÄʾÀý´úÂ룬ÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹¸ºÔ𽫡°Scene¡±ÀàµÄʵÀý×¢È뵽ÿ¸ö²âÊÔ·½·¨ÖС£SceneÀàÈòâÊÔÓÃÀý±àдÕßÄܹ»Ê¹Óá°given¡±¡¢¡°then¡±ºÍ¡°when¡±µÈ²½ÖèÀ´¶¨Ò峡¾°£¨ÐÐΪ£©¡£SceneÀàÊÇÎÒÃÇ×Ô¶¨ÒåÀ©Õ¹µÄÖÐÐĵ¥Ôª£¬Ëü°üº¬ÁËÌØ¶¨ÓÚ²âÊÔ·½·¨µÄ״̬ÐÅÏ¢¡£×´Ì¬ÐÅÏ¢¿ÉÒÔÔÚ³¡¾°µÄ¸÷¸ö²½ÖèÖ®¼ä´«µÝ¡£ÎÒÃÇʹÓá°BeforeEachCallback¡±½Ó¿ÚÔÚµ÷ÓòâÊÔ·½·¨Ö®Ç°×¼±¸Ò»¸öSceneʵÀý£ºÈçǰËùÊö£¬JupiterÒýÇæ½«Ìṩһ¸öÓÃÓÚÔËÐÐÀ©Õ¹Ö´ÐÐÉÏÏÂÎÄ¡£ÎÒÃÇʹÓÃÉÏÏÂÎÄÀ´È·¶¨ÕýÔÚÖ´ÐеIJâÊÔ·½·¨ÊÇ·ñʹÓÃÁË¡°@Scenario¡±×¢½â¡£

public class StoryExtension implements BeforeEachCallback {
@Override
public void beforeEach(ExtensionContext context) throws Exception {
Scene scene = new Scene()
.setDescription(getValue(context, Scenario.class));

Class<?> clazz = context.getRequiredTestClass();

StoryDetails details = context.getStore(NAMESPACE)
.get(clazz.getName(), StoryDetails.class);

details.put(scene.getMethodName(), scene);
}
}

ÉÏÃæµÄ´úÂëÓëÎÒÃÇÔÚ¡°BeforeAllCallback¡±½Ó¿Ú·½·¨ÖÐËù×öµÄ·Ç³£ÏàËÆ¡£

¶¯Ì¬²ÎÊý½âÎö

ÏÖÔÚÎÒÃÇ»¹È±ÉÙÒ»¸ö¶«Î÷£¬¼´ÈçºÎ½«³¡¾°ÊµÀý×¢Èëµ½²âÊÔ·½·¨ÖС£JupiterµÄÀ©Õ¹Ä£ÐÍΪÎÒÃÇÌṩÁËÒ»¸ö¡°ParameterResolver¡±½Ó¿Ú¡£Õâ¸ö½Ó¿ÚΪ²âÊÔÒýÇæÌṩÁËÒ»ÖÖ·½·¨£¬ÓÃÓÚʶ±ðÏ£ÍûÔÚ²âÊÔÖ´ÐÐÆÚ¼ä¶¯Ì¬×¢Èë²ÎÊýµÄÀ©Õ¹¡£ÎÒÃÇÐèҪʵÏÖÕâ¸ö½Ó¿ÚµÄÁ½¸ö·½·¨£¬ÒÔ±ã×¢ÈëÎÒÃǵij¡¾°ÊµÀý£º

import org.junit.jupiter.api.extension.ParameterResolver;

public class StoryExtension implements ParameterResolver {
@Override
public boolean supportsParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) {
Parameter parameter = parameterContext.getParameter();

return Scene.class.equals(parameter.getType());
}

@Override
public Object resolveParameter(ParameterContext parameterContext,
ExtensionContext extensionContext) {
Class<?> clazz = extensionContext.getRequiredTestClass();

StoryDetails details = extensionContext.getStore(NAMESPACE)
.get(clazz.getName(), StoryDetails.class);

return details.get(extensionContext
.getRequiredTestMethod().getName());
}
}

ÉÏÃæµÄµÚÒ»¸ö·½·¨¸æËßJupiterÎÒÃǵÄ×Ô¶¨ÒåÀ©Õ¹ÊÇ·ñ¿ÉÒÔ×¢Èë²âÊÔ·½·¨ËùÐèµÄ²ÎÊý¡£

ÔÚµÚ¶þ¸ö·½·¨¡°resolveParameter()¡±ÖУ¬ÎÒÃÇ´ÓÖ´ÐÐÉÏÏÂÎĵĴ洢ÖлñÈ¡StoryDe??tailsʵÀý£¬È»ºó´ÓStoryDetailsʵÀýÖлñÈ¡ÏÈǰΪ¸ø¶¨²âÊÔ·½·¨´´½¨µÄ³¡¾°ÊµÀý£¬²¢½«Æä´«¸ø²âÊÔÒýÇæ¡£²âÊÔÒýÇæ½«Õâ¸ö³¡¾°ÊµÀý×¢Èëµ½²âÊÔ·½·¨Öв¢Ö´ÐвâÊÔ¡£Çë×¢Ò⣬½öµ±¡°supportsParameter()¡±·½·¨·µ»Øtrueֵʱ²Å»áµ÷Óá°resolveParameter()¡±·½·¨¡£

×îºó£¬ÎªÁËÔÚÖ´ÐÐÍêËùÓйÊʺͳ¡¾°ºóÉú³É±¨¸æ£¬×Ô¶¨ÒåÀ©Õ¹ÊµÏÖÁË¡°AfterAllCallback¡±½Ó¿Ú£º

import org.junit.jupiter.api.extension.AfterAllCallback;

public class StoryExtension implements AfterAllCallback {
@Override
public void afterAll(ExtensionContext context) throws Exception {

new StoryWriter(getStoryDetails(context)).write();
}
}

¡°StoryWriter¡±ÊÇÒ»¸ö×Ô¶¨ÒåÀ࣬¿ÉÉú³É±¨¸æ²¢½«Æä±£´æµ½JSON»òÎı¾ÎļþÖС£

ÏÖÔÚ£¬ÈÃÎÒÃÇ¿´¿´ÈçºÎʹÓÃÕâ¸ö×Ô¶¨ÒåÀ©Õ¹À´±àдBDD·ç¸ñµÄ²âÊÔÓÃÀý¡£Gradle 4.6¼°¸ü¸ß°æ±¾Ö§³ÖʹÓÃJUnit 5ÔËÐе¥Ôª²âÊÔ¡£Äã¿ÉÒÔʹÓÃbuild.gradleÎļþÀ´ÅäÖÃJUnit 5¡£

dependencies {
testCompile group: ¡°ud.junit.bdd¡±, name: ¡°bdd-junit¡±,
version: ¡°0.0.1-SNAPSHOT¡±

testCompile group: ¡°org.junit.jupiter¡±, name: ¡°junit-jupiter-api¡±,
version: ¡°5.2.0"
testRuntime group: ¡°org.junit.jupiter¡±, name: ¡°junit-jupiter-engine¡±,
version: ¡°5.2.0¡±
}

test {
useJUnitPlatform()
}

 

ÈçÄãËù¼û£¬ÎÒÃÇͨ¹ý¡°useJUnitPlatform()¡±·½·¨ÒªÇógradleʹÓÃJUnit 5¡£È»ºóÎÒÃǾͿÉÒÔʹÓÃStoryExtensionÀàÀ´±àд²âÊÔÓÃÀý¡£ÕâÊDZ¾ÎÄ¿ªÍ·¸ø³öµÄʾÀý£º

import org.junit.jupiter.api.extension.ExtendWith;

import ud.junit.bdd.ext.Scenario;
import ud.junit.bdd.ext.Story;
import ud.junit.bdd.ext.StoryExtension;

@ExtendWith(StoryExtension.class)
@Story(name=¡°Returns go back to the stockpile¡±, description=¡°...¡°)
public class StoreFrontTest {

@Scenario(¡°Refunded items should be returned to the stockpile¡±)
public void refundedItemsShouldBeRestocked(Scene scene) {
scene
.given(¡°customer bought a blue sweater¡±,
() -> buySweater(scene, ¡°blue¡±))

.and(¡°I have three blue sweaters in stock¡±,
() -> assertEquals(3, sweaterCount(scene, ¡°blue¡±),
¡°Store should carry 3 blue sweaters¡±))

.when(¡°the customer returns the blue sweater for a refund¡±,
() -> refund(scene, 1, ¡°blue¡±))

.then(¡°I should have four blue sweaters in stock¡±,
() -> assertEquals(4, sweaterCount(scene, ¡°blue¡±),
¡°Store should carry 4 blue sweaters¡±))
.run();
}
}

ÎÒÃÇ¿ÉÒÔͨ¹ý¡°gradle testClasses¡±À´ÔËÐвâÊÔ£¬»òÕßʹÓÃÆäËûÖ§³ÖJUnit 5µÄIDE¡£³ýÁ˳£¹æµÄ²âÊÔ±¨¸æÍ⣬×Ô¶¨ÒåÀ©Õ¹»¹ÎªËùÓвâÊÔÀàÉú³ÉBDDÎĵµ¡£

½áÂÛ

ÎÒÃÇÃèÊöÁËJUnit 5À©Õ¹Ä£ÐÍÒÔ¼°ÈçºÎÀûÓÃËüÀ´´´½¨×Ô¶¨ÒåÀ©Õ¹¡£ÎÒÃÇÉè¼Æ²¢ÊµÏÖÁËÒ»¸ö×Ô¶¨ÒåÀ©Õ¹£¬²âÊÔÓÃÀý±àдÕß¿ÉÒÔʹÓÃËüÀ´´´½¨ºÍÖ´ÐйÊÊ¡£¶ÁÕß¿ÉÒÔ´ÓGitHubÉÏ»ñÈ¡´úÂ룬²¢Ñо¿ÈçºÎʹÓÃJupiterÀ©Õ¹Ä£Ðͼ°ÆäAPIÀ´ÊµÏÖ×Ô¶¨ÒåÀ©Õ¹¡£

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

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

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

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