Mock Test Framework Mockito

Source: Internet
Author: User
Tags throwable

Whether it's agile development, continuous delivery, or test-driven development (TDD), unit testing is the cornerstone of implementation. As these advanced programming patterns become increasingly popular, unit testing is now becoming more and more important. In agile development, continuous delivery requires unit testing to be fast (no access to the actual file system or database), and TDD often encounters a situation where collaboration modules are not yet developed, and mock technology is the panacea for these problems.

The purpose and function of mock technology is to simulate some objects that are not easily constructed or more complex in the application, thus isolating the test from objects outside the bounds of the test.

We can write our own custom mock objects to implement mock techniques, but writing custom mock objects requires additional coding and may introduce errors. There are a lot of excellent open-source frameworks for mock technology now, this paper gives a brief introduction to several typical mock test frameworks, and we hope to help you.

1.EasyMock

EasyMock is an early and popular mock testing framework. It provides a simulation of the interface, the ability to record, replay, check three steps to complete the general testing process, you can verify the method call type, number, order, you can make the Mock object return the specified value or throw a specified exception. By EasyMock, we can construct Mock objects conveniently so that the unit test is carried out smoothly.

EasyMock is an open source project using the MIT license, which can be downloaded from the Sourceforge. (http://sourceforge.net/projects/easymock/files/EasyMock/)

If you use Maven, you can also introduce the following:

<dependency>  <groupId>org.easymock</groupId>  <artifactid>easymock</ artifactid>  <version>3.1</version>  <scope>test</scope></dependency>

Using Easymock can be roughly divided into the following steps:

① use EasyMock to generate Mock objects;

② recording the expected behavior and output of a Mock object;

③ to switch the Mock object to the playback state;

④ call Mock object method for unit test;

⑤ validates the behavior of the Mock object.

Now use an example to simply present the above steps, assuming that there is a class that needs to be emulated as follows:

public class Class1mocked {         public  string Hello (string name) {                   System.out.println ("Hello" +name);                   Return "Hello" +name;         }         public void Show () {                   System.out.println ("Class1mocked.show ()");}         }

The first way to statically import Easymock:

Import static org.easymock.easymock.*;

Example 1.1 Easymock First example
@Testpublic void Testmockmethod () {         class1mocked obj = Createmock (class1mocked.class); ①         expect (Obj.hello (" Z3 ")). Andreturn (" Hello L4 "), ②         Replay (obj), ③         String actual = Obj.hello (" Z3 "); ④         assertequals (" Hello L4 ", actual);         Verify (obj); ⑤}

During the ⑤ validation phase, the mock objects are rigorously verified to occur as expected (including the order and number of executions) as recorded.

2.mockito

A popular mock tool after Easymock. Relatively easymock learning costs are low, and with a very concise API, test code readability is high.

Mockito can be downloaded on https://code.google.com/p/mockito/, if using Maven can be introduced as follows:

<dependency>  <groupId>org.mockito</groupId>  <artifactid>mockito-all</ artifactid>  <version>1.9.5</version>  <scope>test</scope></dependency>

Using Mockito can be roughly divided into the following steps:

① use Mockito to generate Mock objects;

② define (not record) the behavior and output of Mock objects (expectations section);

③ call Mock object method for unit test;

④ validates the behavior of the Mock object.

Now use an example to simply present the above steps:

The first way to statically import Mockito:

Import static org.mockito.mockito.*;
Example 2.1 Mockito First example
@Testpublic void Testmockmethod () {    class1mocked obj=mock (class1mocked.class); ① when    (Obj.hello ("Z3")). Thenreturn ("Hello L4"); ②    String Actual=obj.hello ("Z3"); ③    assertequals ("Hello L4", actual);        Verify (obj). Hello ("Z3"), ④    //verify (obj,times (1)). Hello ("Z3");//can add parameter verification number}

You can see that the switch to playback status is less than the easymock. This is natural, it is not recorded to talk about playback, and in the validation phase you can add parameters (time (int), atleastonce (), atLeast (int), never (), etc.) to accurately verify the number of calls.

If you want to verify that the call order can be controlled as follows:

Example 2.2 Verification sequence
@Testpublic void Testmockmethodinorder () {    class1mocked objother = mock (class1mocked.class);    class1mocked OBJCN = mock (class1mocked.class);    When (Objother.hello ("Z3")). Thenreturn ("Hello L4");    When (Objcn.hello ("Z3")). Thenreturn ("Hello Zhang San");    String other = Objother.hello ("Z3");    Assertequals ("Hello L4", other);    String cn = Objcn.hello ("Z3");    Assertequals ("Hello Zhang San", CN);    Inorder inorder = inorder (Objother, OBJCN); This row does not determine the order, and the following two lines begin the validation order    inorder.verify (objother). Hello ("Z3");    Inorder.verify (OBJCN). Hello ("Z3");}

In the previous simulation operation, we always simulated an entire class or object, and for the function specified by the When (). Thenreturn () method, the system returns the default values of various types (the specific values can refer to the official documentation). The simulated object created by local simulation is still the original system object, although the method when () can be used to specify the return value of some concrete method, but the function that is not modified by this function still executes in the way of the original class of the system, Thenreturn The following are examples of non-local and local simulations, respectively:

Example 2.3 Non-local simulation
@Testpublic void Testskipexpect () {    class1mocked obj = mock (class1mocked.class);    Assertequals (NULL, Obj.hello ("Z3"));    Obj.show ();    Verify (obj). Hello ("Z3");    Verify (obj). Show ();

The above code omits the expectations section (that is, defining code behavior and output), and running the test can see that the Hello method returns null by default (the Show method is not a return value), and none of the two methods in the console output any statements.

There are two ways to Mockito local simulations, one is the Docallrealmethod () mode and the other is the spy () mode.

Example 2.4 Local simulation Docallrealmethod () mode
@Testpublic void Testcallrealmethod () {    class1mocked obj = mock (class1mocked.class);    Docallrealmethod (). When (obj). Hello ("Z3");         Assertequals ("Hello Z3", Obj.hello ("Z3"));    Assertequals (Null,obj.hello ("L4"));    Obj.show ();    Verify (obj). Hello ("Z3");    Verify (obj). Hello ("L4");    Verify (obj). Show ();

Running this test will find that the old code executes when the hello ("Z3") is executed, while the execution of hello ("L4") returns the default value null and no output is printed, and execution show () does not print.

Example 2.5 local analog spy () mode
@Testpublic void Testspy () {    class1mocked obj = Spy (new class1mocked ());        DoNothing (). When (obj). Show ();        Assertequals ("Hello Z3", Obj.hello ("Z3"));    Obj.show ();        Verify (obj). Hello ("Z3");    Verify (obj). Show ();

Running this test will find that the old code executes when the hello ("Z3") is executed, but there is no print statement in the console when you execute Show ().

It is noteworthy, however, that the syntax used in the expectations section of the Mockito Psy () model is different, and the execution is subtly different, as follows:

Example 2.6 notable "traps"
@Testpublic void TestSpy2 () {    class1mocked obj = Spy (new class1mocked ());        When (Obj.hello ("Z3")). Thenreturn ("Hello L4");        Assertequals ("Hello L4", Obj.hello ("Z3"));        Verify (obj). Hello ("Z3");}

Although the above code runs smoothly, it outputs the Hello Z3 in the console, stating that the actual code is still executing, except that Mockito replaces the return value at the end. However, the following code will not execute the actual code:

@Testpublic void TestSpy3 () {    class1mocked obj = Spy (new class1mocked ());        Doreturn ("Hello L4"). When (obj). Hello ("Z3");        Assertequals ("Hello L4", Obj.hello ("Z3"));        Verify (obj). Hello ("Z3");}
3.PowerMock

This tool is extended on Easymock and mockito to solve problems that easymock and Mockito cannot solve, such as static, final, and private methods. In fact, the test architecture well-designed code, generally do not need these features, but if the existing projects to add unit testing, old code has a problem and can not be changed, you have to use these features.

Powermock the same API as the extended framework when extending the functionality, developers familiar with the simulation frameworks supported by Powermock will find powermock very easy to use. The purpose of Powermock is to implement additional functionality by adding very few methods and annotations to interfaces that are now familiar to everyone. Currently, Powermock only extends EasyMock and Mockito, and needs to be used with EasyMock or Mockito mates.

Powermock can be downloaded in https://code.google.com/p/powermock/, this article takes Powermock+mockito as an example, using MAVEN, add the following dependencies, MAVEN will automatically introduce the Mockito package.

<dependency>  <groupId>org.powermock</groupId>  <artifactId> Powermock-api-mockito</artifactid>  <version>1.5</version><scope>test</scope> </dependency><dependency>  <groupId>org.powermock</groupId>  <artifactId> Powermock-module-junit4</artifactid>  <version>1.5</version><scope>test</scope ></dependency>

Now for example the use of Powermock, suppose there is a class that needs to be modeled as follows:

public class Class2mocked {public    static int getdouble (int i) {        return i*2;    }    Public String gettriplestring (int i) {        return multiply3 (i) + "";    }    private int Multiply3 (int i) {        return i*3;    }}

The first way to statically import Powermock:

Import static org.powermock.api.mockito.powermockito.*;

Then make the following statement on the test class using JUNIT4:

@RunWith (Powermockrunner.class) @PrepareForTest ({class2mocked.class})
Example 3.1 simulation of static methods
@Testpublic void Testmockstaticmethod () {    mockstatic (class2mocked.class);    When (class2mocked.getdouble (1)). Thenreturn (3);    int actual = class2mocked.getdouble (1);    Assertequals (3, Actual);    Verifystatic ();    Class2mocked.getdouble (1);}

Powermockit's local simulation is used in a similar way to Mockito (after all, extended Mockito), but the power is that it can simulate private methods, common methods, and final methods. Simulating the common method and the final method is the same as simulating the private method, which is an example of simulating private methods.

Example 3.2 simulating private methods (Docallrealmethod mode)
@Testpublic void Testmockprivatemethod () throws Exception {    class2mocked obj = mock (class2mocked.class);        When (obj, "Multiply3", 1). Thenreturn (4);    Docallrealmethod (). When (obj). gettriplestring (1);        String actual = obj.gettriplestring (1);    Assertequals ("4", actual);        Verifyprivate (obj). Invoke ("Multiply3", 1); }
Example 3.3 simulating private methods (Spy mode)
@Testpublic void TestMockPrivateMethod2 () throws Exception {    class2mocked obj = Spy (new class2mocked ());    When (obj, "Multiply3", 1). Thenreturn (4);    String actual = obj.gettriplestring (1);    Assertequals ("4", actual);    Verifyprivate (obj). Invoke ("Multiply3", 1); }

In addition, Powermock can also simulate the construction method as follows:

Example 3.4 Simulation Construction method
@Test public void Teststructurewhenpathdoesntexist () throws Exception {     final String directorypath = "mocked path"; 
   file Directorymock = mock (file.class);     Whennew (File.class). Witharguments (DirectoryPath). Thenreturn (Directorymock);     When (Directorymock.exists ()). Thenreturn (true);     File File=new file (directorypath);    Asserttrue (File.exists ());     Verifynew (File.class). witharguments (DirectoryPath);     Verifyprivate (Directorymock). Invoke ("exists");}
4.Jmockit

Jmockit is a lightweight mock-up framework, a set of tools and APIs designed to help developers write test programs based entirely on the Java 5 SE java.lang.instrument package, using the ASM library internally to modify Java bytecode.

Jmockit functions and Powermock are similar, some features are even more powerful, but the individual feels that their code is not readable.

Jmockit can be downloaded from https://code.google.com/p/jmockit/, using MAVEN to add the following dependencies:

<dependency>  <groupId>com.googlecode.jmockit</groupId>  <artifactId>jmockit< /artifactid>  <version>1.0</version>  <scope>test</scope></dependency>

Jmockit can also be classified as nonlocal simulation and local simulation, which distinguishes whether the expectations block has parameters, the parameters are local simulations, and the inverse is non-local simulation. The expectations block is generally defined by the expectations class and the Nonstrictexpectations class. Defined by the expectations class, the mock object can only invoke the method in the order defined in the expectations block at run time, cannot be called more or less, so it is possible to omit the verifications block , the Nonstrictexpectations class does not have these restrictions, so if you need to validate, you add a verifications block.

Now illustrate the use of Jmockit:

Example 4.1 Non-local simulation expectations class definition
@Mocked  //objects labeled with @mocked do not need to be assigned, Jmockit automatically mockclass1mocked obj; @Testpublic void TestMockNormalMethod1 () {    new Expectations () {        {            Obj.hello ("Z3");            Returns ("Hello L4", "Hello W5");            Obj.hello ("Zhang San");            result= "Hello John Doe";        }    ;    Assertequals ("Hello L4", Obj.hello ("Z3"));    Assertequals ("Hello W5", Obj.hello ("Z3"));    Assertequals ("Hello John Doe", Obj.hello ("Zhang San"));    try {        Obj.hello ("Z3"),    } catch (Throwable e) {        System.out.println ("The third call to Hello (\" z3\ ") throws an exception");    }    try {        obj.show ();    } catch (Throwable e) {        System.out.println ("Call method not defined in expectations block show () will throw an exception");    }}
Example 4.2 Non-local simulation nonstrictexpectations class definition
public void TestMockNormalMethod2 () {    new nonstrictexpectations () {        {            Obj.hello ("Z3");            Returns ("Hello L4", "Hello W5");        }    ;    Assertequals ("Hello L4", Obj.hello ("Z3"));    Assertequals ("Hello W5", Obj.hello ("Z3"));    Assertequals ("Hello W5", Obj.hello ("Z3"));//Returns the last return value defined in the Nonstrictexpectations block    obj.show ();    New Verifications () {        {            Obj.hello ("Z3");            times = 3;            Obj.show ();            times = 1;}}    ;}

Running this test will find that the show () method does not output a print statement in the console, stating that Jmockit has also made a default mock of the Show method.

Example 4.3 Local simulation
@Testpublic void Testmocknormalmethod () throws IOException {    final class1mocked obj = new class1mocked ();// It is also possible to use the final keyword    new nonstrictexpectations (obj) {        {            Obj.hello ("Z3")            without @mocked annotations; result = "Hello L4";        }    ;    Assertequals ("Hello L4", Obj.hello ("Z3"));    Assertequals ("Hello Zhang San", Obj.hello ("Zhang San"));    New Verifications () {        {            Obj.hello ("Z3");            times = 1;            Obj.hello ("Zhang San");            times = 1;}}    ;}

Running this test finds that hello ("Z3") returns the value defined by the expectations block, but hello ("Zhang San") executes the actual code.

Example 4.4 Simulation of static methods
@Testpublic void Testmockstaticmethod () {    new nonstrictexpectations (class2mocked.class) {        {            Class2mocked.getdouble (1);            result = 3;        }    };    Assertequals (3, class2mocked.getdouble (1));    New Verifications () {        {            class2mocked.getdouble (1);            times = 1;}}    ;}

Example 4.5 simulating a private method
@Testpublic void Testmockprivatemethod () throws Exception {    final class2mocked obj = new class2mocked ();    New Nonstrictexpectations (obj) {        {            this.invoke (obj, "Multiply3", 1);            result = 4;        }    };    String actual = obj.gettriplestring (1);    Assertequals ("4", actual);    New Verifications () {        {            this.invoke (obj, "Multiply3", 1);            times = 1;}}    ;}
Example 4.6 Setting the value of a private property

Suppose there is a class that needs to be emulated as follows:

public class Class3mocked {    private String name = "Name_init";    Public String GetName () {        return name;    }        private static String classname= "Class3mocked_init";        public static String GetClassName () {        return className;    }        public static int getdouble (int i) {        return i*2;    }        public int gettriple (int i) {        return i*3;    }}

You can set the value of a private property as follows:

@Testpublic void Testmockprivateproperty () throws IOException {    final class3mocked obj = new class3mocked ();    New Nonstrictexpectations (obj) {        {            This.setfield (obj, "name", "Name has Bean change!");        }    };    Assertequals ("name has Bean change!", obj.getname ());}
Example 4.7 Setting the value of a static private property
@Testpublic void Testmockprivatestaticproperty () throws IOException {    new nonstrictexpectations ( Class3mocked.class) {        {            This.setfield (class3mocked.class, "ClassName", "ClassName has bean change!");        }    };    Assertequals ("ClassName has bean change!", class3mocked.getclassname ());}
Example 4.8 rewriting the contents of a common method
@Testpublic void Testmocknormalmethodcontent () throws IOException {    final class3mocked obj = new class3mocked ();    New Nonstrictexpectations (obj) {        {            new mockup<class3mocked> () {                @Mock public                int gettriple (int i) {                    return i *;};}    ;    Assertequals (Obj.gettriple (1));    Assertequals (Obj.gettriple (2));}
Example 4.9 rewriting the contents of a static method

If you want to overwrite the static GetDouble method of the Class3mocked class, you need to create a new class that contains the same function declaration as the GetDouble method, with the @mock callout, as follows:

public class Class4mocked {    @Mock public    static int getdouble (int i) {        return i*20;    }}

Can be rewritten as follows:

@Testpublic void Testdynamicmockstaticmethodcontent () throws IOException {    Mockit.setupmock (Class3mocked.class, Class4mocked.class);    Assertequals (class3mocked.getdouble (1));    Assertequals (+, class3mocked.getdouble (2));}

Mock Test Framework Mockito

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.