Use JUnit4 piling test and JMockit

1. What is Mock

Project in each module, each class will have between interdependent relationship, in unit tests, we only care about the unit being tested for its dependent units are not concerned (there will be another test for that unit).

For example, a Class A logical layer number extraction method dependent data access layer class B, then processing logic. In the A unit testing, we are concerned about the return of the query results in different time B, A is how to deal with, rather than B in the end is how to take a number, how packaged as a model and so on.

Therefore, to block out the external dependencies, and Mock let us have a simulation environment.

Currently there are several industry Mock, here the most comprehensive selection of JMockit summarized.

2. JMockit Profile

JMockit works asm is modified by the original class bytecode, and then replace the contents of an existing class using the instrument jdk mechanism, so as to achieve the purpose of the mock.

JMockit used here is version 1.21, the specific use may not the same as with other versions, but the idea is the same. Maven configuration is as follows:

<dependency>
  <groupId>org.jmockit</groupId> 
  <artifactId>jmockit</artifactId> 
  <version>1.21</version>
  <scope>test</scope>
</dependency>

JMockit There are two test methods for a behavior-based, one is based on the state tests.

1) Behavior-oriented(Expectations & Verifications)  

2)State-oriented(MockUp<GenericType>)   

Popular speak, Behavior-oriented behavior is based on mock, mock object code of behavior to imitate, more like a black box . State-oriented state is based on mock, standing inside the target test code. May be made to the parameters passed inspection, the match will return something similar to white box. State-oriented but basically the new MockUp mock any code or logic.

Suppose there are two classes, Service and DAO. Service database query by a number of different groups of goods, whether the goods get sold.

Package com.khlin.test.junit.jmockit.demo; 

public  class -Service { 
    
    Private the DAO DAO; 
    
    public  void setDao (the DAO DAO) {
         the this .dao = DAO; 
    } 
    
    / ** 
     * The inventory is determined whether the goods sold 
     * @param Group 
     * @return 
     * / 
    public the Status the checkStatus (String Group) {
         int COUNT = the this .dao.getStoreCount (Group); 

        IF (COUNT <= 0 ) {
             return Status.UNKOWN; 
        } the else  IF (COUNT <= 800) {
            return Status.UNSALABLE;
        } else if (count <= 1000) {
            return Status.NORMAL;
        } else {
            return Status.SELLINGWELL;
        }
    }
}


package com.khlin.test.junit.jmockit.demo;

import java.util.HashMap;
import java.util.Map;

public class DAO {

    private Map<String, Integer> groupCounts = new HashMap<String, Integer>();

    /**
     * 假数据
     */
    {
        this.groupCounts.put("A", 500);
        this.groupCounts.put("B", 1000);
        this.groupCounts.put("C", 1200);
    }

    public int getStoreCount(String group) {
        Integer count = this.groupCounts.get(group);

        return null == count ? -1 : count.intValue();
    }
}
Package com.khlin.test.junit.jmockit.demo; 

public  enum the Status { 

    / ** 
     * sold 
     * / 
    SELLINGWELL, 
    / ** 
     * General 
     * / 
    the NORMAL, 
    / ** 
     * unmarketable 
     * / 
    UNSALABLE, 
    
    / ** 
     * status unknown 
     * / 
    UNKOWN 
}

 

Mock behavior-based test, a total of three stages: record, replay, verify.

1) record: At this stage, a variety of methods expected to be called will be recorded in the actual implementation.

2) repaly: At this stage, unit testing Case, originally recorded in the record stage of the calls may have the opportunity to be executed. There is "likely" to emphasize that not recorded it will be strictly enforced.

3) verify: At this stage, the results of tests or other assertion is whether the original would expect.

Suppose now I just want to test Service, in the case of inventory 900 whether the state can return to NORMAL correct. Well, I do not care about in the end is what DAO incoming packet, nor how to care DAO database access, I just want to let DAO return 900, so that you can test the Service.

Sample code:

@RunWith (. JMockit class )
 public  class ServiceBehavier { 

    @Mocked 
    the DAO DAO = new new the DAO (); 

    Private -Service-Service = new new -Service (); 

    @Test 
    public  void Test () { 

        // 1. Record Record expectation 
        new new NonStrictExpectations () { 
            { 
                / ** 
                 * the method of recording 
                 * / 
                dao.getStoreCount (AnyString); // the mock this method, whatever the value of type String passed, return the same value, to the effect of the black box 
                / ** 
                 * expected results, Back 900 
                 * / 
                Result = 900;
                 / ** 
                Times must be called twice. In Expectations must be called, otherwise it will error, there is no need for calibration. 
                In NonStrictExpectations not mandatory requirements, but it seems to be verified has verify the mandatory. 
                Further there maxTimes, minTimes 
                * / 
                Times =. 1 ; 
            } 
        }; 
        service.setDao (DAO); 

        // 2. Replay call 
        Assert.assertEquals (Status.NORMAL, service.checkStatus ( "D" )); 

//         Assert.assertEquals (Status.NORMAL, service.checkStatus ( "D")); 

         // 3. Is the check only called once. If the above statement is a comment and then transferred once, and the recorded times to 2, it will be an error in the validation stage. 
        new new Verifications () {  
            {
                dao.getStoreCount (AnyString);
                times = 1;
            }
        };

    }
}

 

Mock test based on the state of

By MockUp class of direct overwrite code logic mock classes, somewhat similar to the white box.

public class ServiceState {

    private DAO dao;
    
    private Service service;

    @Test
    public void test() {
        
        //1. mock对象
        MockUp<DAO> mockUp = new MockUp<DAO>() {

            @Mock
            public int getStoreCount(String group) {
                return 2000;
            }
        };
        
        //2. 获取实例
        dao = mockUp.getMockInstance();
        service = new Service();
        service.setDao(dao);
        
        //3. Call 
        Assert.assertEquals (Status.SELLINGWELL, service.checkStatus ( "FFF" )); 
        
        // 4. restored objects, avoiding mutual influence between test method. In fact, no impact on one instance, the greater impact on the static method. Old version tearDown () method is static Mockit class 
        mockUp.tearDown (); 
    } 
}

 

3. JMockit mock sample code types or methods

Abstract class 

package com.khlin.test.junit.jmockit.demo.jmockit;

public abstract class AbstractA {
    
    public abstract int getAbstractAnything();

    public int getAnything() {
        return 1;
    }
}

Interface classes

package com.khlin.test.junit.jmockit.demo.jmockit;

public interface InterfaceB {
    
    public int getAnything();
}

General Category

package com.khlin.test.junit.jmockit.demo.jmockit;

public class ClassA {
    
    InterfaceB interfaceB;
    
    private int number;
    
    public void setInterfaceB(InterfaceB interfaceB) {
        this.interfaceB = interfaceB;
    }
    
    public int getAnything() {
        return getAnythingPrivate();
    }
    
    private int getAnythingPrivate() {
        return 1;
    }
    
    public int getNumber() {
        return number;
    }
    
    
    
    public static int getStaticAnything(){
        return getStaticAnythingPrivate();
    }
    
    private static int getStaticAnythingPrivate() {
        return 1;
    }
    
    public int getClassBAnything() {
        return this.interfaceB.getAnything();
    }
}

Interface implementation class

package com.khlin.test.junit.jmockit.demo.jmockit;

public class ClassB implements InterfaceB {

    public int getAnything() {
        return 10;
    }
    
}

The ultimate test code

package com.khlin.test.junit.jmockit.demo;

import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Injectable;
import mockit.Mock;
import mockit.MockUp;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import mockit.Tested;
import mockit.Verifications;
import mockit.integration.junit4.JMockit;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

import com.khlin.test.junit.jmockit.demo.jmockit.AbstractA;
import com.khlin.test.junit.jmockit.demo.jmockit.ClassA;
import com.khlin.test.junit.jmockit.demo.jmockit.ClassB;
import com.khlin.test.junit.jmockit.demo.jmockit.InterfaceB;

@RunWith(JMockit.class)
public class JMockitTest {

    /**
     * mock私有方法
     */
    @Test
    public void testPrivateMethod() {

        final ClassA a = new ClassA();
        // 局部参数,把a传进去
        new NonStrictExpectations(a) {
            {
                Deencapsulation.invoke(a, "getAnythingPrivate");
                result = 100;
                times = 1;
            }
        };

        Assert.assertEquals(100, a.getAnything());

        new Verifications() {
            {
                Deencapsulation.invoke(a, "getAnythingPrivate");
                times = 1;
            }
        };
    }

    /**
     * mock私有静态方法
     */
    @Test
    public void testPrivateStaticMethod() {

        new NonStrictExpectations(ClassA.class) {
            {
                Deencapsulation
                        .invoke(ClassA.class, "getStaticAnythingPrivate");
                result = 100;
                times = 1;
            }
        };

        Assert.assertEquals(100, ClassA.getStaticAnything());

        new Verifications() {
            {
                Deencapsulation
                        .invoke(ClassA.class, "getStaticAnythingPrivate");
                times = 1;
            }
        };

    } 

    / ** 
     * mock公有方法
     * / 
    @Test 
    public  void testPublicMethod () {
         final ClassA classes = new ClassA ();
        new NonStrictExpectations (classes) { 
            { 
                classA.getAnything (); 
                result = 100 ; 
                times = 1 ; 
            } 
        }; 

        Assert.assertEquals ( 100 , classA.getAnything ()); 

        new verification () { 
            { 
                classA.getAnything (); 
                times = 1 ;
            } 
        }; 
    } 

    / ** 
     * the mock public static method - based Behavior 
     * / 
    @Test 
    public  void testPublicStaticMethod () { 

        new new NonStrictExpectations (of ClassA. Class ) { 
            { 
                ClassA.getStaticAnything (); 
                Result = 100 ; 
                Times =. 1 ; 
            } 
        }; 

        Assert.assertEquals ( 100 , ClassA.getStaticAnything ()); 

        new new Verifications () { 
            {
                ClassA.getStaticAnything();
                Times ; =. 1 
            } 
        }; 
    } 
    
    / ** 
     * the mock public static methods - based on the status 
     * / 
    @Test 
    public  void testPublicStaticMethodBaseOnStatus () { 

        MockUp <of ClassA> = MockUp new new MockUp <of ClassA> () { 
            @Mock 
            public  int getStaticAnything () { // Note that not declared as static 
                return 100 ; 
            } 
        }; 
        
        Assert.assertEquals ( 100 , ClassA.getStaticAnything ()); 
    } 
    
    / ** 
     * the mock interfaces 
     * / 
    @Test 
    public  void testInterface() {
        
        InterfaceB interfaceB = new MockUp<InterfaceB>() {
            @Mock
            public int getAnything() {
                return 100;
            }
        }.getMockInstance();
        
        
        ClassA classA = new ClassA();
        classA.setInterfaceB(interfaceB);
        
        Assert.assertEquals(100, classA.getClassBAnything());
    }
    
    /**
     * mock接口--基于状态
     */
    @Test
    public void testInterfaceBasedOnStatus() {
        final InterfaceB interfaceB = new ClassB();
        
        new NonStrictExpectations(interfaceB) {
            {
                interfaceB.getAnything();
                result = 100;
                times = 1;
            }
        };
        
        ClassA classA = new ClassA();
        classA.setInterfaceB(interfaceB);
        
        Assert.assertEquals(100, classA.getClassBAnything());
        
        new Verifications() {
            {
                interfaceB.getAnything();
                times = 1;
            }
        };
    }
    
    
    
    /**
     * mock抽象类
     */
    @Test
    public void testAbstract() {
        AbstractA abstractA = new MockUp<AbstractA>() {
            @Mock
            public int getAbstractAnything(){
                return 100;
            }
            
            @Mock
            public int getAnything(){
                return 1000;
            }
        }.getMockInstance();
        
        Assert.assertEquals(100, abstractA.getAbstractAnything());
        
        Assert.assertEquals(1000, abstractA.getAnything());
    }
}

 

Guess you like

Origin www.cnblogs.com/wsy0202/p/11374123.html