SSH框架下單元測試的實現

SSH框架下單元測試的實現

實現的功能

  • 實現了部門的增刪改查
  • 對Action進行了單元測試
  • 對Service 進行了單元測試,經過mock的方式實現。web

    實現的步驟

    1、對Action層的單元測試實現
    一、首先在pom文件中須要引入的依賴spring

    <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
          </dependency>
          <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
          </dependency>
          <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-junit-plugin</artifactId>
            <version>2.1.8</version>
            <scope>test</scope>
          </dependency>
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.2.8.RELEASE</version>
          </dependency>

    說明:
    在此處咱們引入struts2-junit-plugin.2.1.8.jar,由於其裏面有測試Struts2中action的類
    StrutsSpringTestCase,用來測試ssh中的action。
    二、新建一個測試類
    若是你使用的是idea,那麼你能夠直接在須要創建測試類的Action類中
    按ctrl+shift+t,新建一個測試類。如DepartmentActionTest
    三、若是是普通的action的話,
    待測試代碼:apache

    public String findById() {
                  String did = ServletActionContext.getRequest().getParameter("did");
                  department=departmentService.findByDid(Integer.valueOf(did));
                  return "goEditDepartment";
              }

    測試代碼:json

    @Test
              public void testFindById() throws Exception {
                   /*這個函數至關@Before註解的函數,是調用單元測試後的時候,
                 首先會執行的方法。能夠在這裏面作一些必要的準備工做*/
                  request.setParameter("did", "1");
                  ActionProxy proxy = getActionProxy("/department_findById.action");
                  DepartmentAction action = (DepartmentAction) proxy.getAction();
                  String result = action.findById();
                  Assert.assertEquals("goEditDepartment", result);
              }

    四、若是是返回json的action的話,待測試代碼:api

    public void  findAll() {
             List<Department> departmentList= departmentService.findAll();
             JSONObject jsonObject = new JSONObject();
             if (CollectionUtils.isEmpty(departmentList)) {
                 jsonObject.put("key", "success");
                 jsonObject.put("data", JSON.toJSONString(departmentList));
                 writeJson(jsonObject);
                 return;
             }
             jsonObject.put("key", "success");
             jsonObject.put("data", JSON.toJSONString(departmentList));
             writeJson(jsonObject);
         }

    測試代碼:session

    String result = executeAction("/json_findAll.action");
            Assert.assertNotNull(result);
            JSONObject jsonObject = JSON.parseObject(result);
            if ("success".equals(jsonObject.getString("key"))) {
                List<Department> departmentList = JSON.parseArray(jsonObject.getString("data"), Department.class);
                if (CollectionUtils.isEmpty(departmentList)) {
                    return;
                }
                for (Department department : departmentList) {
                    System.out.println(department.toString());
                }
            }

    五、關於lazy問題的解決:首先在setUp()函數中加入下述代碼:app

    @Override
             protected void setUp() throws Exception {
                 super.setUp();
                 SessionFactory sessionFactory = lookupSessionFactory(request);
                 Session hibernateSession= getSession(sessionFactory);
                 TransactionSynchronizationManager.bindResource(sessionFactory,
                         new SessionHolder(hibernateSession));
                 //在只讀模式下(FlushMode.NEVER/MANUAL)寫操做不被容許
                 hibernateSession.setFlushMode(FlushMode.AUTO);
             }

    而後在添加兩個私有函數框架

    private Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
            Session session = sessionFactory.openSession();
            FlushMode flushMode = FlushMode.NEVER;
            if (flushMode != null) {
                session.setFlushMode(flushMode);
            }
            return session;
        }
        private SessionFactory lookupSessionFactory(HttpServletRequest request) {
            //「sessionFactory」是你spring配置文件(一般是application.xml)中的SessionFactory。
            //如:org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean
            return (SessionFactory)this.applicationContext.getBean("sessionFactory");
        }

    說明:經過lookupSessionFactory()方法獲取這個測試環境中的org.hibernate.SessionFactory實體對象,其中
    applicationContext是org.springframework.context.ApplicationContext的實現org.springframework.context.support.GenericApplicationContext
    咱們能夠經過它的getBean方法來獲取你配置文件中配置的SessionFactory。使用註解是org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean
    不須要使用註解的時候可使用org.springframework.orm.hibernate.LocalSessionFactoryBean來實現。dom

    該單元測試須要加載spring配置文件信息,默認加載路徑是你項目的src目錄下,文件名默認爲applicationContext.xml,若是路徑不對或者
    文件名不一樣,則須要重寫getContextLocations()方法,如ssh

    protected String getContextLocations() {
            return "classpath*:applicationContext.xml";
        }

    關於實現web session的問題,很簡單,該類提供了一個MockHttpServletRequest成員變量,咱們只要mock一個session出來,而後加入到這個request中,就能夠實現session的模擬了。示例代碼以下:

    HttpSession  session = new MockHttpSession();
     String sessionId = UUID.randomUUID().toString();
     session.setAttribute(ConstParameter.USER_SESSION, sessionId);
     //user是一個用戶信息的類,你能夠根據你的須要本身定義
     UserInfor user = new UserInfo();
     user.setUserId(1);
     user.setName("xxx");
     session.setAttribute(ConstParameter.USER_INFO, user);
     request.setSession(session);

    關於action的單元測試咱們就說完了。
    2、Service的單元測試
    接下來咱們在說說關於service的測試,
    一樣,咱們先從依賴提及,須要添加的依賴:

    <powermock.version>1.7.1</powermock.version>
    
       <!--********************powermock使用*********************-->
            <dependency>
              <groupId>org.powermock</groupId>
              <artifactId>powermock-module-junit4</artifactId>
              <version>${powermock.version}</version>
              <scope>test</scope>
            </dependency>
            <dependency>
              <groupId>org.powermock</groupId>
              <artifactId>powermock-api-mockito</artifactId>
              <version>${powermock.version}</version>
              <scope>test</scope>
            </dependency>

    此處咱們採用的是powermock+junit 進行mock測試。爲啥使用powermock呢,毋庸置疑,因爲他的功能比較強大
    一、首先,咱們咱們看看待測試的代碼:
    @Override public List<MyInvoice> getMyInvoice(String buyerId) { if (StringUtils.isBlank(buyerId)) { return null; } List<MyInvoice> myInvoices = new ArrayList<MyInvoice>(); String url = baseDataUrl + UrlConfig.GET_MYINVOICE_URL + "?t=" + VerifyBaseUtil.getT() + "&token=" + VerifyBaseUtil.getToken() + "&buyerId=" + buyerId; System.out.println("MyInvoiceServiceImpl getMyInvoice接口請求參數爲:" + url); try { String responseInfo = HttpUtil.getHttp(url); System.out.println("MyInvoiceServiceImpl getMyInvoice接口返回結果爲:" + responseInfo); Map<String, Object> result = JSON.parseObject(responseInfo, Map.class); if (DistrictReturnNum.SUCCESS.getValue().equals(result.get("code"))) { myInvoices = JSON.parseArray(JSON.toJSONString(result.get("result")), MyInvoice.class); return myInvoices; } } catch (Exception e) { System.out.println("MyInvoiceServiceImpl getMyInvoice 程序出錯,查詢發票失敗"+e.getMessage()); return null; } return null; }
    getMyInvoice方法是一個調用外部接口的方法,經過http協議進行通訊。這兒有兩個問題
    1.HttpUtil.getHttp(url) 是一個靜態方法,咱們如何mock?
    2.咱們如何mock這個方法所在的實現類?由於該實現類是經過spring ioc 容器生成並注入的。

要回答這兩個問題,咱們首先須要看看,咱們的測試代碼:
```
@RunWith(PowerMockRunner.class)
@PrepareForTest(HttpUtil.class)
public class MyInvoiceServiceImplTest {
@InjectMocks
private MyInvoiceService myInvoiceService = new MyInvoiceServiceImpl();
@Before
public void setUp(){
PowerMockito.mockStatic(HttpUtil.class);
}
@Test
public void testGetMyInvoice() throws Exception {
String result_http="{"result":[{"addDate":1509010776000,"buyerId":" +
""9E59A2D27B7748848FB65041B854240E","headName":"項偉測試"," +
""headType":"0","invoiceId":"9747A51B57FF4EA781F1CFDF73A0D9DF"," +
""invoiceType":"0","isDefault":0},{"addDate":1509092635000,"" +
"buyerId":"9E59A2D27B7748848FB65041B854240E","editDate":1509094177000,"headName":"項偉測試二","headType":"0","invoiceId":"720CF6C50E594283B01C79D03D6D52B2"" +
","invoiceType":"0","isDefault":1}],"msg":"成功","code":104}";
// 一、 buyerId爲空
String buyerId = null;
Assert.assertEquals(null, myInvoiceService.getMyInvoice(buyerId));
// 二、buyerId不爲空
buyerId = "FF8080810F5E601526";
PowerMockito.when(HttpUtil.getHttp(anyString())).thenReturn(result_http);
List result = myInvoiceService.getMyInvoice(buyerId);
Assert.assertEquals(2,result.size());
}
}

```
第一個問題:咱們經過PowerMockito.mockStatic(HttpUtil.class); 一個靜態方法的實現類。而後就能夠調用該靜態方法。
第二個問題:@InjectMocks註解來mock咱們須要測試的業務類。
至此,咱們就能夠經過powermock對service層的方法進行單元測試了。

運行環境

  • 環境描述:Struts2+Spring4.2.4+hibernate4
    JAVA 1.7
  • 額外依賴第三方jar包,請參考pom.xml
相關文章
相關標籤/搜索