欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Spring測試

         測試的時(shí)候會(huì )破壞數據庫現場(chǎng),如果兩次都執行添加的測試用例,那么會(huì )拋出主鍵重復的異常,另外測試方法中都要手動(dòng)去獲得Service對象,硬編碼;使用Spring提供的測試機制:

1.       保護數據庫現場(chǎng)

2.       2.通過(guò)IOCService注入來(lái)獲取其對象,而不是硬編碼

3.       查看數據庫中的實(shí)際值

 

Spring的測試包為spring-test.jar文件(某些版本的測試包可能在spring-mock.jar下,具體應用時(shí)請檢查對應的class文件是否存在),

 

ConditionalTestCase

它本身和Spring沒(méi)有任何關(guān)聯(lián),可用于任何單元測試中,他僅僅是添加了一個(gè)按條件執行測試方法的功能。在單元測試中,所有帶test前綴的方法都會(huì )被毫無(wú)例外的執行,現在的junit4X版本可以通過(guò)加一個(gè)@Test注解,而不用遵守這個(gè)約定。而繼承ConditionalTestCase,可以讓你在某些情況下,有選擇的關(guān)閉掉某些測試方法。

         只需要實(shí)現ConditionalTestCaseisDisabledInThisEnvironment方法,ConditionalTestCase在運行每個(gè)方法千,會(huì )根據isDisabledInThisEnvironment判斷是否為要執行的方法,某人情況下,返回false,也就是執行所有方法。

         public void runBare() throws Throwable {

      // getName will return the name of the method being run

      if (isDisabledInThisEnvironment(getName())) {

         recordDisabled();

         logger.info("**** " + getClass().getName() + "." +

            getName() + " disabled in this environment: " +

            "Total disabled tests=" + getDisabledTestCount());

         return;

      }

     

      // Let JUnit handle execution

      super.runBare();

   }

 

/**

    * Should this test run?

    * @param testMethodName name of the test method

    * @return whether the test should execute in the current envionment

    */

   protected boolean isDisabledInThisEnvironment(String testMethodName) {

      return false;

   }

 

AbstractSpringContextTests

擴展自ConditionalTestCase,它維護了一個(gè)static類(lèi)型的緩存器,使用鍵保存了Spring ApplicationContext實(shí)例,這意味著(zhù),不同的用例,不同測試方法都可以共享這個(gè)實(shí)例,也就是說(shuō),在運行多個(gè)測試用例和測試方法時(shí),Spring容器只需要實(shí)例化一次就可以了。

 

private static Map contextKeyToContextMap = new HashMap();

 

 

 

AbstractSingleSpringContextTests

繼承自AbstractSpringContextTests,她通過(guò)一些方法讓你更方便地制定Spring配置文件所在位置:

  • String[] getConfigLocations():該方法允許你在指定Spring配置文件時(shí)使用資源類(lèi)型前綴,這些資源類(lèi)型前綴包括:classpath:、file:。以類(lèi)似于“com/baobaotao/beans.xml”形式指定的資源被當成類(lèi)路徑資源處理;
  • String[] getConfigPaths():以“/”開(kāi)頭的地址被當成類(lèi)路徑處理,如“/com/baobaotao/beans.xml”,而未以“/”開(kāi)頭的地址被當成相對于測試類(lèi)所在包的文件路徑,如“beans.xml”表示配置文件在測試類(lèi)所在類(lèi)包的目錄下;
  • String getConfigPath():和getConfigPaths()類(lèi)似,在僅需指定一個(gè)配置文件中使用。

 

protected final void setUp() throws Exception {

      this.applicationContext = getContext(contextKey());

      prepareTestInstance();

      onSetUp();

}

 

protected final void tearDown() throws Exception {

      onTearDown();

}

 

我可以看到,該類(lèi)將steUptearDown覆蓋為final的,所以我們在子類(lèi)中就不能自己再去覆蓋這些類(lèi)了。setUp的作用就是確保創(chuàng )建了配置文件所執行的容器。

 

this.applicationContext = getContext(contextKey());

該方法建立了applicationContext,而contextKLey方法方法:

protected Object contextKey() {

      return getConfigLocations();

}

 

protected String[] getConfigLocations() {

      String[] paths = getConfigPaths();

      String[] locations = new String[paths.length];

      for (int i = 0; i < paths.length; i++) {

         String path = paths[i];

         if (path.startsWith("/")) {

            locations[i] = ResourceUtils.CLASSPATH_URL_PREFIX +

                path;

         }

         else {

            locations[i] = ResourceUtils.CLASSPATH_URL_PREFIX +

                   StringUtils.cleanPath(

ClassUtils.classPackageAsResourcePath(

getClass()) + "/" + path);

         }

      }

      return locations;

}

 

protected String[] getConfigPaths() {

      String path = getConfigPath();

      return (path != null ? new String[] {path} : new String[0]);

}

 

protected String getConfigPath() {

      return null;

   }

 

我們從這里可以看出他們的優(yōu)先級的原因,另外再看一下getContext()方法,他是以final的形式寫(xiě)在父類(lèi)AbstractSpringContextTests中的

/**

    * Obtain an ApplicationContext for the given key, potentially cached.

    * @param key the context key

    * @return the corresponding ApplicationContext instance (potentially cached)

    */

   protected final ConfigurableApplicationContext getContext(Object key) throws Exception {

      String keyString = contextKeyString(key);

      ConfigurableApplicationContext ctx =

            (ConfigurableApplicationContext) contextKeyToContextMap.get(keyString);

      if (ctx == null) {

         ctx = loadContext(key);

         ctx.registerShutdownHook();

         contextKeyToContextMap.put(keyString, ctx);

      }

      return ctx;

   }

 

 

可以看出這個(gè)方法的意思是先到緩存中查找context,如果沒(méi)找到context則創(chuàng )建。而作為hashkey,則是以路徑的某種形式作為key的。

 

另外,loadContext在這里類(lèi)中并沒(méi)有做任何事,而是交給之類(lèi)去實(shí)現的:

protected ConfigurableApplicationContext loadContextLocations(String[] locations) throws Exception {

   ++this.loadCount;

   if (logger.isInfoEnabled()) {

         logger.info("Loading context for locations: " +

      StringUtils.arrayToCommaDelimitedString(locations));

   }

      return createApplicationContext(locations);

}

 

protected ConfigurableApplicationContext createApplicationContext(String[] locations) {

      GenericApplicationContext context = new

         GenericApplicationContext();

      customizeBeanFactory(

context.getDefaultListableBeanFactory());

      new XmlBeanDefinitionReader(context).

loadBeanDefinitions(locations);

      context.refresh();

      return context;

   }

 

 

AbstractDependencyInjectionSpringContextTests

在前面的類(lèi)都準備好一些基礎方法之后,AbstractDependencyInjectionSpringContextTests提供了自動(dòng)依賴(lài)注入的功能,無(wú)需手工從容器中獲取目標bean進(jìn)行裝配。類(lèi)似于ByType的方式:

 

package com.baobaotao.test;

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

import com.baobaotao.service.UserService;

 

public class DependencyInjectionCtxTest extends

AbstractDependencyInjectionSpringContextTests {

private UserService userService;  

 

public void  setUserService(UserService userService) {該屬性設置方法會(huì )被自動(dòng)調動(dòng)  

               this.userService = userService;

}

@Override

protected String[] getConfigLocations() { 指定Spring配置文件所在位置

               return new String[]{"baobaotao-service.xml","baobaotao-dao.xml"};

}

public void testHasMatchUser(){ 測試方法

               boolean match = userService.hasMatchUser("tom","123456");

assertEquals(true,match);

}

}

 

<beans> 
<tx:annotation-driven/> 
按類(lèi)型匹配于DependencyInjectionCtxTestuserService屬性 
<bean id="userService" class="com.baobaotao.service.UserServiceImpl"> 
<property name="userDao" ref="userDao"/> 
<property name="loginLogDao" ref="loginLogDao"/> 
</bean>
</beans>

 

 

指定了Spring配置文件所在的位置,AbstractDependencyInjectionSpringContextTests將使用這些配置文件初始化好Spring容器,并將它們保存于static的緩存中。然后馬上著(zhù)手根據類(lèi)型匹配機制(byType),自動(dòng)將Spring容器中匹配測試類(lèi)屬性的Bean通過(guò)Setter注入到測試類(lèi)中。

 

他覆蓋了父類(lèi)的prepareTestInstance方法,在準備好容器之后,馬上注入依賴(lài):

protected void prepareTestInstance() throws Exception {

      injectDependencies();

}

 

 

 

protected void injectDependencies() throws Exception {

      if (isPopulateProtectedVariables()) {

         if (this.managedVariableNames == null) {

            initManagedVariableNames();

         }

         populateProtectedVariables();

      }

      else if (getAutowireMode() != AUTOWIRE_NO) {

         getApplicationContext().getBeanFactory()

.autowireBeanProperties( this,

 getAutowireMode(), isDependencyCheck());

      }

   }

 

自動(dòng)裝配的問(wèn)題

采用這種byType的自動(dòng)裝配方式,有時(shí)候會(huì )帶來(lái)一些問(wèn)題,當容器中擁有多個(gè)匹配類(lèi)型的Bean的時(shí)候,就會(huì )拋出UnsatisfiedDependencyException異常。假設我們采用以下傳統的事務(wù)管理的配置方式對UserService進(jìn)行配置,按類(lèi)型匹配的自動(dòng)裝配機制就會(huì )引發(fā)問(wèn)題:

用于被代理的目標Bean,按類(lèi)型匹配于UserService

<bean id="userServiceTarget" class="com.baobaotao.service.UserServiceImpl">
<property name="userDao"
ref="userDao" />
<property name="loginLogDao"
ref="loginLogDao"></property>
</bean>

通過(guò)事務(wù)代理工廠(chǎng)為UserServiceImpl創(chuàng )建的代理Bean,也按匹配于UserService

<bean id="userService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"
ref="transactionManager" />
<property name="target"
ref="userServiceTarget" />
<property name="transactionAttributes">

</property>
</bean>

由于處和處的Bean都按類(lèi)型匹配于UserService,在對DependencyInjectionCtxTestuserService屬性進(jìn)行自動(dòng)裝配將會(huì )引發(fā)問(wèn)題。有兩種針對該問(wèn)題的解決辦法:

1.調整配置文件,使按類(lèi)型匹配于UserServiceBean僅有一個(gè),具體有以下兩個(gè)方法:

  • 處的Bean作為處的內部Bean進(jìn)行裝配;
  • 使用基于注解驅動(dòng)的事務(wù)管理配置機制,這樣就無(wú)需在配置文件中定義兩個(gè)UserServiceBean了。關(guān)于注解驅動(dòng)事務(wù)管理配置的詳細信息。

2.改變DependencyInjectionCtxTest的自動(dòng)裝配機制:Spring默認使用byType類(lèi)型的自動(dòng)裝配機制,但它允許你通過(guò)setAutowireMode()的方法改變默認自動(dòng)裝配的機制,比如你可以調用setAutowireMode(AUTOWIRE_BY_NAME)方法啟用按名稱(chēng)匹配的自動(dòng)裝配機制。

AbstractDependencyInjectionSpringContextTests定義了三個(gè)代表自動(dòng)裝配機制類(lèi)型的常量,分別說(shuō)明如下:

  • AUTOWIRE_BY_TYPE:按類(lèi)型匹配的方式進(jìn)行自動(dòng)裝配,這個(gè)默認的機制;
  • AUTOWIRE_BY_NAME:按名字匹配的方式進(jìn)行自動(dòng)裝配
  • AUTOWIRE_NO:不使用自動(dòng)裝配機制,這意味著(zhù)你需要手工調用getBean()進(jìn)行裝配。

依賴(lài)檢查

假設我們在DependencyInjectionCtxTest添加一個(gè)User類(lèi)型的屬性并提供Setter方法,而Spring容器中沒(méi)有匹配該屬性的Bean。在默認情況下, AbstractDependencyInjectionSpringContextTests要求所有屬性都能在Spring容器中找到對應Bean,否則拋出異常。

仔細思考一下,這種運行機制并非沒(méi)有道理,因為既然你已經(jīng)提供了Setter方法,就相當于給出了這樣的暗示信息:這個(gè)屬性測試類(lèi)自身創(chuàng )建不了,必須由外部提供。而在使用自動(dòng)裝配機制的情況下,測試類(lèi)屬性自動(dòng)從Spring容器中注入匹配的屬性,一般情況下不會(huì )手工去調用Setter方法準備屬性。

如果你出于一些特殊的理由,希望在采用自動(dòng)裝配的情況下,如果有屬性未得到裝配也不在乎,那么你可以在測試類(lèi)構造函數中調用setDependencyCheck(false)方法達到目的:

package com.baobaotao.test;

public class DependencyInjectionCtxTest extends AbstractDependencyInjectionSpringContextTests {
public DependencyInjectionCtxTest(){
setDependencyCheck(
false); 告知不進(jìn)行屬性依賴(lài)性檢查
}

}

 

 

不寫(xiě)setter方法的注入

大部分IDE都有了為字段生成setter的方式,所以寫(xiě)setter方法其實(shí)沒(méi)什么必要,Spring提供了這種注入方式,本質(zhì)上是通過(guò)反射去獲得Field的。只需要在構造函數中調用:

 

將需要自動(dòng)裝配的屬性變量聲明為protected;

 setPopulateProtectedVariables(true)方法(聯(lián)系上面的源碼)。

 

可能大家對第一點(diǎn)比較奇怪,看一下里面調用的一個(gè)方法就知道了:

private void initManagedVariableNames() throws IllegalAccessException {

      LinkedList managedVarNames = new LinkedList();

      Class clazz = getClass();

 

      do {

         Field[] fields = clazz.getDeclaredFields();

         ……….

         for (int i = 0; i < fields.length; i++) {

            Field field = fields[i];

               ….

            if (isProtectedInstanceField(field)) {

                …..

            }

         }

         clazz = clazz.getSuperclass();

      }

      while (!clazz.equals(AbstractDependencyInjectionSpringContextTests.class));

 

      this.managedVariableNames = (String[]) managedVarNames.toArray(new String[managedVarNames.size()]);

   }

 

private boolean isProtectedInstanceField(Field field) {

      int modifiers = field.getModifiers();

      return !Modifier.isStatic(modifiers) &&

         Modifier.isProtected(modifiers);

   }

 

AbstractTransactionalSpringContextTests

繼承了上面一個(gè)類(lèi),他的作用就是能夠讓事務(wù)回滾。UserService以下兩個(gè)接口方法會(huì )對數據庫執行更改操作:

void loginSuccess(User user);
void registerUser(User user);

當我們對這兩個(gè)接口方法進(jìn)行測試時(shí),它們將會(huì )在數據庫中產(chǎn)生持久化數據??紤]對registerUser(User user)方法進(jìn)行測試時(shí),我們可能編寫(xiě)如下所示的測試方法:

public void testRegisterUser(){
User user =
new User();
user.setUserId(2);
user.setUserName("john");
user.setPassword("123456");
userService.registerUser(user);
}

當第一次成功運行testRegisterUser()測試方法時(shí),將在數據庫中產(chǎn)生一條主鍵為2的記錄,如何第二次重新運行testRegisterUser()測試方法其結果將不言自明:因主鍵沖突導致測試方法執行失敗,最終報告測試用例沒(méi)有通過(guò)。在這種情況下,測試用例未通過(guò)并不是因為UserServiceImpl#registerUser(User user)存在邏輯錯誤,而是因為測試方法的積累效應導致外在設施的現場(chǎng)發(fā)生變化而引起的問(wèn)題。

AbstractTransactionalSpringContextTests專(zhuān)為解決以上問(wèn)題而生,也就是說(shuō)前面我們所提個(gè)問(wèn)題在此得到了回答。只要繼承該類(lèi)創(chuàng )建測試用例,在默認情況下,測試方法中所包含的事務(wù)性數據操作都會(huì )在測試方法返回前被回滾。由于事務(wù)回滾操作發(fā)生在測試方法返回前的點(diǎn)上,所以你可以象往常一樣在測試方法體中對數據操作的正確性進(jìn)行校驗。

package com.baobaotao.service;
import org.springframework.test.AbstractTransactionalSpringContextTests;
import com.baobaotao.domain.User;
public class UserServiceIntegrateTest extends AbstractTransactionalSpringContextTests {
  private UserService userService;
public void setUserService(UserService userService) {
   this.userService = userService;
}
@Override
protected String[] getConfigLocations() {
   return new String[]{"baobaotao-service.xml", "baobaotao-dao.xml"};
}
   public void testRegisterUser(){

①  測試方法中的數據操作將在方法返回前被回滾,不會(huì )對數據庫
     User user =
new User(); 產(chǎn)生永久性數據操作,第二次運行該測試方法時(shí),依舊可以
     user.setUserId(2);
成功運行。
     user.setUserName("john");
     user.setPassword("123456");
     userService.registerUser(user);


  User user1 = userService.findUserByUserName("john");
對數據操作進(jìn)行
   assertEquals(user.getUserId(), user1.getUserId());
正確性檢驗
 }

}

如果testRegisterUser()是直接繼承于AbstractDependencyInjectionSpringContextTests類(lèi)的測試方法,則重復運行該測試方法就會(huì )發(fā)生數據沖突問(wèn)題。但因為它位于繼承于AbstractTransactionalSpringContextTests的測試用例類(lèi)中,測試方法中對數據庫的操作會(huì )被正確回滾,所以重復運行不會(huì )有任何問(wèn)題。

 

如果你確實(shí)希望測試方法中對數據庫的操作持久生效而不是被回滾,Spring也可以滿(mǎn)足你的要求,你僅需要在測試方法中添加setComplete()方法就可以了。

 public void testRegisterUser(){

User user1 = userService.findUserByUserName("john");
assertEquals(user.getUserId(), user1.getUserId());
setComplete(); 測試方法中的事務(wù)性數據操作將被提交
}

AbstractTransactionalSpringContextTests還擁有幾個(gè)可用于初始化測試數據庫,并在測試完成后清除測試數據的方法,分別介紹如下:

  • onSetUpBeforeTransaction()/onTearDownAfterTransaction():子類(lèi)可以覆蓋這兩個(gè)方法,以便在事務(wù)性測試方法運行的前后執行一些數據庫初始化的操作并在事務(wù)完成后清除之;
  • onSetUpInTransaction()/onTearDownInTransaction():這對方法和前面介紹的方法完成相同的功能,只不過(guò)它們是在測試方法的相同事務(wù)中執行的。

AbstractTransactionalSpringContextTests另外還提供了一組用于測試延遲數據加載的方法:endTransaction()/startNewTransaction()。我在測試Hibernate、JPA等允許延遲數據加載的應用時(shí),如何模擬數據在Service層事務(wù)中被部分加載,當傳遞到Web層時(shí)重新打開(kāi)事務(wù)完成延遲部分數據加載的測試場(chǎng)景呢?這兩個(gè)方法即為此用途而生:你可以在測試方法中顯式調用endTransaction()方法以模擬從Service層中獲取部分數據后返回,爾后,再通過(guò)startNewTransaction()開(kāi)啟一個(gè)和原事務(wù)無(wú)關(guān)新事務(wù)——模擬在Web層中重新打開(kāi)事務(wù),接下來(lái)你就可以訪(fǎng)問(wèn)延遲加載的數據,看是否一切如期所料了。

在代碼清單 6處,我們通過(guò)UserService#findUserByUserName()方法對前面registerUser(user)方法數據操作的正確性進(jìn)行檢驗。應該說(shuō),我們非常幸運,因為在UserService中剛好存在一個(gè)可用于檢測registerUser(user)數據操作正確性的方法。讓我們考慮另外的一種情況:要是 UserService不存在這樣的方法,我們該如何檢測registerUser(user)數據操作結果的正確性呢?顯然我們不能使用肉眼觀(guān)察的方法,那難道為了驗證數據操作正確性專(zhuān)門(mén)編寫(xiě)一個(gè)配合性的數據訪(fǎng)問(wèn)類(lèi)不成?

效驗結果正確性AbstractTransactionalSpringContextTests

它添加了一個(gè)JdbcTemplate,你可以借由此道快意直達數據庫。它自動(dòng)使用Spring容器中的數據源(DataSource)創(chuàng )建好一個(gè)JdbcTemplate實(shí)例并開(kāi)放給子類(lèi)使用。值得注意的是,如果你采用byName自動(dòng)裝配機制,數據源Bean的名稱(chēng)必須取名為“dataSource”。

 

import org.springframework.test.AbstractTransactionalDataSourceSpringContextTests;

public class UserServiceIntegrateWithJdbcTest
extends AbstractTransactionalDataSourceSpringContextTests {

① 注意:繼承類(lèi)發(fā)生調整
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
protected String[] getConfigLocations() {
return new String[]{"baobaotao-service.xml", "baobaotao-dao.xml"};
}
public void testRegisterUser(){
User user =
new User();
user.setUserId(2);
user.setUserName("john");
user.setPassword("123456");
userService.registerUser(user);
String sqlStr = " SELECT user_id FROM t_user WHERE user_name ='john' ";
int userId = jdbcTemplate.queryForInt(sqlStr);
可以直接使用JdbcTemplate訪(fǎng)問(wèn)數據庫了
assertEquals(user.getUserId(), userId);
setComplete();

}
}

jdbcTemplateAbstractTransactionalDataSourceSpringContextTests類(lèi)中定義的,子類(lèi)可以直接使用它訪(fǎng)問(wèn)數據庫。這樣我們就可以靈活地訪(fǎng)問(wèn)數據庫以檢驗目標測試方法的數據操作正確性。至此,我們終于畢其功于一役于AbstractTransactionalDataSourceSpringContextTests,順利解決前面我們中指出的最后題。

只要你通過(guò)擴展AbstractTransactionalSpringContextTests及其子類(lèi)創(chuàng )建測試用例,所有測試方法都會(huì )工作了事務(wù)環(huán)境下。也就是說(shuō),即使某些測試方法不需要訪(fǎng)問(wèn)數據庫,也會(huì )產(chǎn)生額外的事務(wù)管理開(kāi)銷(xiāo),是否可以對測試方法啟用事務(wù)管理的行為進(jìn)行控制呢?此外,在一些情況下,除對目標方法邏輯運行的正確性進(jìn)行檢驗外,我們還希望對目標方法的運行性能進(jìn)行測試:如當目標方法運行時(shí)間超過(guò)200毫秒時(shí),則測試用例視為未通過(guò)。諸如此類(lèi)的問(wèn)題,我們目前學(xué)習到的知識還不能很好的應付。Spring 2.0新增了注解驅動(dòng)的測試工具為我們指明了道路,你僅需要通過(guò)簡(jiǎn)單為測試方法標注注解,我們剛才提出的疑難問(wèn)題就可以迎刃而解了。

@Test(timeout = 1000)

http://www.uml.org.cn/j2ee/200905074.asp        

詳細講解在Spring中進(jìn)行集成測試

 

JUnit 4 in 60 Seconds

 

 

 

 

 

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
SpringBoot多數據源事務(wù)管理機制
多用戶(hù)并發(fā)操作的解決方案
數據庫并發(fā)控制技術(shù)(2)
java_筆試題及答案(公司1)
Spring怎么在一個(gè)事務(wù)中開(kāi)啟另一個(gè)事務(wù)
數據庫讀寫(xiě)分離
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久