junit及springJUNIT

在每个单独的功能模块里建测试文件夹写单元测试

springJUNIT用法???

一:eclispe/Myeclipse中已经添加好了junit的jar包,在build path中选择add Library中选择添加junit的jar包即可。如果idea中没有自己下载然后添加即可(在IDEA中添加插件:File-Settings-Plugins,没有可以从仓库中添加)。

二:生成Junit测试框架:

   run——edit  configration——添加junit,在右侧配置configration:

  Test  kind:Method

 Class:测试类

Method:测试方法名

 

三:具体执行:

在打开的类中快捷键ctrl,shift+T即可,然后勾选想要测试的方法,勾选几个测试类中便会创建几个。

四:执行规则:

1.必须用@Test注解进行修饰

2.测试方法必须使用public void修饰,且测试方法不能有任何参数。测试逻辑自己写,其实就是创建目标类的实例然后调用其方法。

3.通常用@before注解的方法来初始化

3.测试类的包要与被测试类的包结构一致。

4.测试单元中的各个测试方法不能有依赖,必须独立测试。

 设置类变量给类变量赋值创建实例private static ... = new ...(或用@beforeClass来进行实例化)

https://www.cnblogs.com/huaxingtianxia/p/5563111.html

http://blog.csdn.net/andycpp/article/details/1327346

 测试本质是创建目标类的实例对实例的方法进行各种操作,必然会改变实例的属性值,对某些实例方法的测试前对实例的属性值有特殊要求,此时便可以使用@before注解的方法来使该属性值变为特定值。

 

assertEquals用来断言基本类型是否相同

assertSame用来断言对象是否相同

 

通常单元测试用来测业务层写的方法

 

junit会遇到spring容器多次初始化的问题吗?

 

 

springJUNIT

 

  1. 导致多次Spring容器初始化问题
    根据JUnit测试方法的调用流程,每执行一个测试方法都会创建一个测试用例的实例并调用setUp()方法。由于一般情况下,我们在setUp()方法 中初始化Spring容器,这意味着如果测试用例有多少个测试方法,Spring容器就会被重复初始化多次。虽然初始化Spring容器的速度并不会太 慢,但由于可能会在Spring容器初始化时执行加载Hibernate映射文件等耗时的操作,如果每执行一个测试方法都必须重复初始化Spring容 器,则对测试性能的影响是不容忽视的;使用Spring测试套件,Spring容器只会初始化一次!

  2. 需要使用硬编码方式手工获取Bean
    在测试用例类中我们需要通过ctx.getBean()方法从Spirng容器中获取需要测试的目标Bean,并且还要进行强制类型转换的造型操作。这种乏味的操作迷漫在测试用例的代码中,让人觉得烦琐不堪;使用Spring测试套件,测试用例类中的属性会被自动填充Spring容器的对应Bean,无须在手工设置Bean!

  3. 数据库现场容易遭受破坏
    测试方法对数据库的更改操作会持久化到数据库中。虽然是针对开发数据库进行操作,但如果数据操作的影响是持久的,可能会影响到后面的测试行为。举个例子, 用户在测试方法中插入一条ID为1的User记录,第一次运行不会有问题,第二次运行时,就会因为主键冲突而导致测试用例失败。所以应该既能够完成功能逻 辑检查,又能够在测试完成后恢复现场,不会留下“后遗症”;使用Spring测试套件,Spring会在你验证后,自动回滚对数据库的操作,保证数据库的现场不被破坏,因此重复测试不会发生问题!

  4. 不方便对数据操作正确性进行检查
    假如我们向登录日志表插入了一条成功登录日志,可是我们却没有对t_login_log表中是否确实添加了一条记录进行检查。一般情况下,我们可能是打开 数据库,肉眼观察  是否插入了相应的记录,但这严重违背了自动测试的原则。试想在测试包括成千上万个数据操作行为的程序时,如何用肉眼进行检查?
    只要你继承Spring的测试套件的用例类,你就可以通过jdbcTemplate在同一事务中访问数据库,查询数据的变化,验证操作的正确性!

1. maven 配置

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.12</version>
    <scope>test</scope>
</dependency>

2.创建BaseJunit4Test基类

创建 Spring Test 的基类,该类主要用来加载配置文件,设置web环境。
所有的测试类,都继承该类即可。

import org.junit.runner.RunWith;  
import org.springframework.test.context.ContextConfiguration;  
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;  
  
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试  
@ContextConfiguration(locations={"classpath:spring.xml","classpath:spring-mvc.xml","classpath:spring-hibernate.xml","classpath:spring-ehcache.xml"}) //加载配置文件
@WebAppConfiguration("src/main/webapp")
//------------如果加入以下代码,所有继承该类的测试类都会遵循该配置,也可以不加,在测试类的方法上///控制事务,参见下一个实例    
//这个非常关键,如果不加入这个注解配置,事务控制就会完全失效!    
//@Transactional    
//这里的事务关联到配置文件中的事务控制器(transactionManager = "transactionManager"),同时//指定自动回滚(defaultRollback = true)。这样做操作的数据才不会污染数据库!    
//@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)    
//------------    
public class BaseJunit4Test{  
      
}
  1. @RunWith(SpringJUnit4ClassRunner.class) 使用junit4进行测试
  2. @ContextConfiguration() 加载spring相关的配置文件
  3. @WebAppConfiguration() 设置web项目的环境,如果是Web项目,必须配置该属性,否则无法获取 web 容器相关的信息(request、context 等信息)

3.测试类

import org.junit.Test;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.test.annotation.Rollback;  
import org.springframework.transaction.annotation.Transactional;  
  
import cn.com.infcn.ade.service.UserManagerService;
import cn.com.infcn.model.pmodel.AdeUser;  
  
public class UserTest extends BaseJunit4Test{  
    @Autowired //自动注入  
    private UserManagerService userManagerService;  
      
    @Test  
    @Transactional   //标明此方法需使用事务    
    @Rollback(false)  //标明使用完此方法后事务不回滚,true时为回滚   
    public void testUser(){  
        System.out.println("测试Spring整合Junit4进行单元测试");  
          
        AdeUser user = userManagerService.get("0");
        System.out.println(user);
        System.out.println("------------"+user.getLoginName());
    }
}  
  1. 使用Spring Test 可以使用@Autowired 自动注入 相关的bean信息,而不需要自己手动通过getBean去获取相应的bean信息。
  2. @Transaction
    使用Spring Test 测试,可以 @Transaction 注解,表示该方法使用spring的事务。
  3. @Rollback(false)
    标明使用完此方法后事务不回滚,true时为回滚。
    比如每次打包或提交时,都执行下所有的测试类,而测试类每次都进行插入或删除数据或导致数据库中的数据不完整,为了防止执行测试类都修改库中的数据,可以设置Rollback(true)。


 

 

同事给的

package com.jd.trip.hotel.sip.collection.test.base;

import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:spring-config.xml", "classpath:net/bull/javamelody/monitoring-spring-aspectj.xml"})
public abstract class BaseTest {
    protected Logger logger = LoggerFactory.getLogger(getClass());
}

 

 

public class HttpClient {
    private AsyncHttpClient client;
    private final static int connectTimeout = 5000;
    private final static int readTimeout = 10000;
    private final static int requestTimeout = 10000;

    private static class HttpClientHolder {//懒加载
        private static HttpClient httpClient = new HttpClient();
    }

    private HttpClient() {
        AsyncHttpClientConfig.Builder configBuilder = new AsyncHttpClientConfig.Builder();
        configBuilder.setConnectTimeout(connectTimeout);
        configBuilder.setReadTimeout(readTimeout);
        configBuilder.setRequestTimeout(requestTimeout);
        this.client = new AsyncHttpClient(configBuilder.build());
    }

    public static HttpClient getAsyncHttpClient() {
        return HttpClientHolder.httpClient;
    }

    public String get(String url) {
        try {
            ListenableFuture<Response> futrue = this.client.prepareGet(url).execute();
            Response res = futrue.get();
            String responseMsg = res.getResponseBody();
            return responseMsg;
        } catch (Exception e) {
            GLogger.error("HttpClient 请求供应商接口--请求失败--请求地址及异常", url.concat("----->").concat(e.getMessage()));
            throw new SoaServiceRpcException(ErrorEnum.SIP_HTTP_BAD_UNKNOWN.getCode(), ErrorEnum.SIP_HTTP_BAD_UNKNOWN.getMessage());
        }
    }

    public ListenableFuture<Response> get(String url, AsyncHandler resHandler) {
        return this.client.prepareGet(url).execute(resHandler);
    }

    private Request buildRequest(String url, Map<String, String> paramsMap) {
        RequestBuilder requestBuilder = new RequestBuilder();
        if (paramsMap != null && paramsMap.size() > 0) {
            Set<Map.Entry<String, String>> entrySet = paramsMap.entrySet();
            Iterator<Map.Entry<String, String>> iterator = entrySet.iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> entry = iterator.next();
                if (entry.getKey() != null) {
                    requestBuilder.addFormParam(entry.getKey(), entry.getValue());
                }
            }
        }
        // 添加RequestHeader,key
        requestBuilder.addHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
        requestBuilder.addHeader("Accept", "application/json");
        requestBuilder.addHeader("connection", "Keep-Alive");
        requestBuilder.addHeader("Content-Length", "0");
        requestBuilder.setMethod("POST");
        requestBuilder.setUrl(url);

        return requestBuilder.build();
    }

    public ListenableFuture<Response> post(String url, Map<String, String> paramsMap) {
        Request req = this.buildRequest(url, paramsMap);
        return this.client.executeRequest(req);
    }

    public void post(String url, Map<String, String> paramsMap, AsyncHandler resHandler) {
        Request req = this.buildRequest(url, paramsMap);
        this.client.executeRequest(req, resHandler);
    }

    public void callBack(com.google.common.util.concurrent.ListenableFuture<Response> future, DeferredResult<String> results) {
        Futures.addCallback(future, new FutureCallback<Response>() {
            @Override
            public void onSuccess(Response result) {
                String responseMsg = null;
                try {
                    responseMsg = analysisInputStream(result);
                    results.setResult(responseMsg);
                } catch (IOException e) {
                    results.setErrorResult(e.getMessage());
                    results.setResult(null);
                }
            }

            @Override
            public void onFailure(Throwable t) {
                results.setErrorResult(t.getMessage());
            }
        });
    }

    public com.google.common.util.concurrent.ListenableFuture<Response> getFuture(ListenableFuture<Response> execute) {
        return new com.google.common.util.concurrent.ListenableFuture<Response>() {
            @Override
            public boolean cancel(boolean mayInterruptIfRunning) {
                return execute.cancel(mayInterruptIfRunning);
            }

            @Override
            public boolean isCancelled() {
                return execute.isCancelled();
            }

            @Override
            public boolean isDone() {
                return execute.isDone();
            }

            @Override
            public Response get() throws InterruptedException, ExecutionException {
                return execute.get();
            }

            @Override
            public Response get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
                return execute.get(timeout, unit);
            }

            @Override
            public void addListener(Runnable listener, Executor executor) {
                execute.addListener(listener, executor);
            }
        };
    }

    public static String analysisInputStream(Response input) throws IOException {
        InputStream inputStream = null;
        InputStreamReader inputStreamReader = null;
        try {
            inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
            char[] szBuffer = new char[1024];
            int result = inputStreamReader.read(szBuffer);
            StringBuffer buffer = new StringBuffer();
            while (result != -1) {
                buffer.append(new String(szBuffer, 0, result));
                result = inputStreamReader.read(szBuffer);
            }
            return buffer.toString();
        } catch (Exception e) {
            return input.getResponseBody("UTF-8");
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
        }
    }

    public String post(String url, String param) {
        Request req = this.buildRequest(url, param);
        return httpPost(req, url);
    }

    protected String httpPost(Request req, String url) {
        try {
            ListenableFuture<Response> future = this.client.executeRequest(req);
            Response res = future.get(requestTimeout, TimeUnit.MILLISECONDS);
            String responseMsg = res.getResponseBody();
            return responseMsg;
        }  catch (TimeoutException e) {
            GLogger.logError("AsyncHttpClient 网络请求超时,url:{},e:{}", url,  ExceptionUtil.LogExceptionStack(e));
            return NetworkErrorEnum.NETWORK_TIME_OUT.getKey();
        }  catch (Exception e) {
            GLogger.logError("AsyncHttpClient 网络异常,url:{}, e:{}", url,  ExceptionUtil.LogExceptionStack(e));
            return NetworkErrorEnum.NETWORK_ERROR.getKey();
        }
    }

    private Request buildRequest(String url, String params) {
        RequestBuilder requestBuilder = new RequestBuilder();
        requestBuilder.addHeader("Content-type", "application/json;charset=utf-8");
        requestBuilder.addHeader("Accept", "application/json");
        requestBuilder.addHeader("connection", "Keep-Alive");
        requestBuilder.addHeader("Content-Length", String.valueOf(params.length()));
        requestBuilder.setMethod("POST");
        requestBuilder.setUrl(url);
        requestBuilder.setBody(params);
        return requestBuilder.build();
    }
}

 

 

 

 

项目示例:

package com.jd.trip.hotel.sip.ctrip.web.test;

import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:spring-config.xml", "classpath:net/bull/javamelody/monitoring-spring-aspectj.xml"})
public abstract class BaseTest {
    protected Logger logger = LoggerFactory.getLogger(getClass());
}

 

package com.jd.trip.hotel.sip.ctrip.web.test.resourceTest;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jd.ihexpedia.common.constant.Constant;
import com.jd.ihexpedia.common.http.HttpClient;
import com.jd.ihexpedia.common.util.GLogger;
import com.jd.ihexpedia.common.util.JsonUtil;
import com.jd.ihexpedia.domain.bo.hotel.ExpediaHotelInfoBO;
import com.jd.trip.hotel.sip.ctrip.web.test.BaseTest;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import sun.text.normalizer.UTF16;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * @description:
 * @author: libin293
 * @requireNo:
 * @createdate: 2018-06-05 14:59
 * @lastdate: 2018/6/5
 */
public class HotelInfoTest extends BaseTest{


    @Test
    public void test() {
        System.out.println("开始执行");

        HttpURLConnection conn = null;
        FileOutputStream out = null;
        BufferedOutputStream bf = null;
        int len = -1;
        try {
            conn = (HttpURLConnection) new URL(Constant.HOTEL_INFO_URL).openConnection();
            HttpURLConnection conn2 = (HttpURLConnection) new URL(Constant.HOTEL_INFO_NAME_MAPPING_URL).openConnection();
            buildConn(conn);
            buildConn(conn2);

            conn.connect();
            conn2.connect();

            Map<String, String> hotelNameMap = Maps.newHashMap();
            Map<String, String> hotelAddressMap = Maps.newHashMap();

            /*hotelName读取*/
            if(conn2.getResponseCode() == 200) {
                ZipInputStream zis2 = new ZipInputStream(conn2.getInputStream());
                FileOutputStream hotelName = new FileOutputStream(new File("HotelName.txt"));
                while ((zis2.getNextEntry()) != null) {
                    while ((len = zis2.read(Constant.readBytes)) > -1) {
                        hotelName.write(Constant.readBytes, 0, len);
                    }
                }
                hotelName.flush();
                hotelName.close();
                zis2.close();
            }

            /*HotelName解析*/
            BufferedReader buffer2 = new BufferedReader(new InputStreamReader(new FileInputStream(new File("HotelName.txt")), "UTF-8"));
            String line1;
            while ((line1 = buffer2.readLine()) != null) {
                String [] line1s = line1.split("\\|");
                if(line1.contains("EANHotelID") || line1s.length <= 4 || !isChinese(line1s[2])) {
                    /*过滤非中文酒店名称*/
                    continue;
                }
                String hotelId = line1s[0];
                String hotelNameCN = line1s[2];
                String hotelAddressCN  =line1s[3];
                hotelNameMap.put(hotelId, hotelNameCN);
                hotelAddressMap.put(hotelId, hotelAddressCN);
            }
            System.out.println("酒店名称解析结果:" + hotelNameMap.size());


            /*HotelInfo读取*/
            List<ExpediaHotelInfoBO> expediaHotelInfoBOList = Lists.newArrayList();
            if (conn.getResponseCode() == 200) {
                ZipInputStream zis = new ZipInputStream(conn.getInputStream());
                FileOutputStream hotelOut = new FileOutputStream(new File("D://HotelInfo.txt"));
                while ((zis.getNextEntry()) != null) {
                    while ((len = zis.read(Constant.readBytes)) > -1) {
                        hotelOut.write(Constant.readBytes, 0, len);
                    }
                }
                hotelOut.flush();
                hotelOut.close();
                zis.close();
                System.out.println("写入文件结束");
            }

            /*HotelInfo解析*/
            BufferedReader buffer = new BufferedReader(new InputStreamReader(new FileInputStream(new File("D://HotelInfo.txt")), "UTF-8"));
            String line;
            while ((line = buffer.readLine()) != null) {
                String [] hotelInfoLines = line.split("\\|");
                if(StringUtils.isEmpty(hotelInfoLines[8]) || !hotelInfoLines[8].trim().equals("CN")) {
                    //过滤非国内酒店
                    continue;
                }
                ExpediaHotelInfoBO expediaHotelInfoBO = new ExpediaHotelInfoBO();
                expediaHotelInfoBO.setHotelCode(hotelInfoLines[0]);
                expediaHotelInfoBO.setHotelNameEn(hotelInfoLines[2]);
                expediaHotelInfoBO.setHotelNameCn(hotelNameMap.get(hotelInfoLines[0]));
                expediaHotelInfoBO.setCityCode(hotelInfoLines[7]);
                expediaHotelInfoBO.setCityName(hotelInfoLines[5]);
                expediaHotelInfoBO.setAddress(hotelAddressMap.get(hotelInfoLines[0]));
                expediaHotelInfoBO.setLatitude(hotelInfoLines[9]);
                expediaHotelInfoBO.setLongitude(hotelInfoLines[10]);
                expediaHotelInfoBOList.add(expediaHotelInfoBO);
            }
            System.out.println("执行结束, 结果:" + JsonUtil.vo2JsonString(expediaHotelInfoBOList.get(0)) + "总数:" + expediaHotelInfoBOList.size());

        } catch (Exception e) {
            GLogger.logError("Expedia-getNativeHotelInfo-下载文件出错e:{}", ExceptionUtils.getStackTrace(e));
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
            if (out != null) {
                try {
                    out.close();
                } catch (Exception e) {
                    GLogger.logError("close FileOutputStream Exception as:{}", ExceptionUtils.getStackTrace(e));
                }
            }
        }
    }


    public void updateNativeHotelInfo() {

    }

    // 判断一个字符串是否含有中文
    public static boolean isChinese(String str) {
        if (str == null) return false;
        for (char c : str.toCharArray()) {
            if (isChinese(c)) return true;// 有一个中文字符就返回
        }
        return false;
    }

    public static boolean isChinese(char c) {
        return c >= 0x4E00 &&  c <= 0x9FA5;// 根据字节码判断
    }


    public static void buildConn(HttpURLConnection connection) throws Exception{
        connection.setDoOutput(true);
        connection.setDoInput(true);
        connection.setUseCaches(false);
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept-Encoding", "gzip, deflate");
        connection.setRequestProperty("Connection", "keep-alive");
        connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36");
    }



    public List<ExpediaHotelInfoBO> readHotelInfoFromTxt(String fileName) throws Exception{
        List<ExpediaHotelInfoBO> expediaHotelInfoBOList = Lists.newArrayList();
        InputStream in = new ClassPathResource(fileName).getInputStream();
        BufferedReader buffer = new BufferedReader(new InputStreamReader(in, "UTF-8"));
        String line;
        while ((line = buffer.readLine()) != null) {
            String [] hotelInfoLines = line.trim().split("\\|");
            ExpediaHotelInfoBO expediaHotelInfoBO = new ExpediaHotelInfoBO();
            expediaHotelInfoBO.setHotelCode(hotelInfoLines[0]);
            expediaHotelInfoBO.setHotelNameEn(hotelInfoLines[2]);
            expediaHotelInfoBO.setCityCode(hotelInfoLines[7]);
            expediaHotelInfoBO.setCityName(hotelInfoLines[5]);
            expediaHotelInfoBO.setAddress("".concat(hotelInfoLines[3]).concat(hotelInfoLines[4]));
            expediaHotelInfoBO.setLatitude(hotelInfoLines[9]);
            expediaHotelInfoBO.setLongitude(hotelInfoLines[10]);
            expediaHotelInfoBOList.add(expediaHotelInfoBO);
        }
        return expediaHotelInfoBOList;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值