Reprint: http://blog.csdn.net/zhoudaxia/article/details/33056093
In peacetime development work, often encounter development progress inconsistent, resulting in the interface you want to call is not good, at this time, you need to provide their own interface to other parties, at this time need to write a mock interface to the other side debugging. Or you need to test whether the interface is valid, but the relying party is not good.
The concept of simulation (mock)
Beyond the world of software development, the term "mock" refers to imitation or emulation. Therefore, "mock" can be understood as a surrogate, a substitute. The reference to "mock" in software development is usually understood as a mock object or fake.
The translator's note: Mock and so on represent the abstract class of the object being simulated, you can interpret fake as an instance of a mock. I do not know that this is not accurate:)
Fake is usually used as a substitute for the dependent relationship of the class being tested .
noun Definitions |
Dependency -dependency refers to the ability of a class to perform its intended function in an application based on another class. Dependencies typically exist in instance variables of the classes that are dependent on them. |
|
Tested classes – When writing unit tests, theterm "unit" usually represents a separate class and the test code written for it. the class under test refers to the class in which it is tested. |
Why do I need simulations?
When we first learned to program, the objects we wrote were usually independent. Classes such as Hello World do not rely on other classes (except System.out) and do not manipulate other classes. But in fact the software is full of dependencies. We will write the Operation class based on the service class, and the service class is based on the data Access Class (DAOs), which goes down.
Figure 1 Classes of dependencies
The idea of unit testing is that we want to test the code without involving dependencies. This test allows you to ignore the dependencies of your code to test the validity of your code. The core idea is that if the code works as designed and the dependencies are normal, then they should work as expected.
The concept of a mock object is that we want to create an object that can replace the actual object. The mock object can invoke a specific method through a specific parameter and return the expected result.
What are the key points of the simulation?
when it comes to simulations, you only need to care about three things: set up the test data, set the expected results, and verify the results. Some unit test scenarios do not involve these at all, and some only involve setting up test data, and some only involve setting expected results and validation.
stubbing (Pile)
Stubbing is telling fake what kind of behavior to perform when interacting with it. Typically it can be used to provide the public properties (like getters and setters) and public methods required for those tests.
When it comes to stubbing methods, usually you have a series of choices. You might want to return a special value, throw an error, or trigger an event, and you may want to indicate different behavior when the method is called (that is, by passing a matching type or parameter to the method).
That sounds like a lot of work, but it's not always the case. An important feature of many mocking frameworks is that you do not need to provide the entity method of the stub, nor do you want to stub those methods that are not called or unused properties during the execution of the test.
set the expected
a key feature of fake is that when you use it for simulation testing, you can tell it what you expect. For example, you can require a specific function to be called exactly 3 times, or not to be called, or to call at least two times but not more than 5 times, or to satisfy a particular type of argument, a specific value, and any combination of these. The possibilities are endless.
Tell fake what you expect to happen by setting the expected results. Because it's a simulation test, nothing actually happens. However, for the class being tested, it is not able to differentiate this situation. So fake can call a function and let it do what it should.
It is important to note that most simulation frameworks can create mock tests of public classes in addition to simulation tests that can create interfaces.
Verifying expected results
Setup expectations and validations are expected to be in parallel. The setting is expected to complete before the function of the test class is called, and the validation is expected after it. So, first you set the desired results and then verify that your expected results are correct.
In a unit test, if the expectations you set are not met, then the unit test fails. For example, you set the expected result that the Iloginservice.login function must be called once with a specific user name and password, but it was not called in the test, and the fake was not validated, so the test failed.
What are the benefits of simulation?
create tests in advance; TDD (test-driven development)
That's the biggest benefit. If you create a mock then you can write the service tests before the service interface is created, so you can add the test to your automated test environment during the development process. In other words, impersonation enables you to use test-driven development.
Teams can work in parallel
This is similar to the point above; create tests for non-existent code. But what we're talking about is that the developers write the test program, which is the test team to create. How does the test team create tests when nothing is being measured? Simulate and test for simulations! This means that when the service excuse needs to be tested, the QA team actually has a complete set of test components, and no one team waits for the other team to finish. This makes the simulation of the benefits of particularly prominent.
You can create a validation or demo program.
Because mocks is very efficient,mocks can be used to create a proof of concept, as one, or as a demo program that you are considering building a project. This provides a strong foundation for you to decide whether the project will be followed, but the most important is to provide practical design decisions.
write tests for inaccessible resources
This benefit does not belong to the actual benefit of a kind, but as a necessary when the "life buoy." Have you encountered such a situation? When you want to test a service interface, but the service needs to be accessed through a firewall, the firewall cannot be opened for you or you need authentication to access it. When this happens, you can use the Mockservice alternative where you can access it, which is a "life buoy" feature.
mocks can be distributed to users
In some cases, you need to allow some external sources to access your test system, like a partner or a customer, for some reason. These reasons cause others to have access to your sensitive information, and you may just want to allow access to some of the test environments. In this case, how do you provide a test system to the partner or customer to develop or test? The simplest is to provide a mock, whether it comes from your network or the customer's network. SoapUI mocks are very easy to configure and can be run in SoapUI or as a war package to your Java server.
Isolation System
Sometimes you want to test a separate part of the system without the impact of other parts of the system. Because other system parts will cause interference to the test data, it affects the test results based on data collection. Using mock you can remove the system-dependent simulations that need to be part of the test. When these mocks are isolated, the mocks becomes very simple and reliable, fast and predictable. This gives you a test environment that removes random behavior, has a repeating pattern, and can monitor a particular system.
Mockito Frame
Mockito is an open source Java testing Framework based on the MIT Protocol.
Mockito distinguishes itself from other simulation frameworks by allowing developers to verify the behavior of the system under test without establishing "expectations". One criticism of mock objects is that the test code is highly coupled to the system being tested, since Mockito attempts to remove the expect-run-verify mode (expected-run-validate mode) by removing the "expected specification", thus minimizing the coupling. This prominent feature simplifies the test code, making it easier to read and modify.
Figure 2 Do not use mock frames
Figure 3 Using the Mockito Framework Step 1: Create a common Java project in the IDE
Create a common Java project in Eclipse, NetBeans, or IntelliJ idea.
Step 2: Add Java source code
Class Person.java:
PackageMockitodemo; Public classPerson {Private FinalInteger PersonID; Private FinalString PersonName; PublicPerson (Integer PersonID, String personname) { This. PersonID =PersonID; This. PersonName =PersonName; } PublicInteger Getpersonid () {returnPersonID; } PublicString Getpersonname () {returnPersonName; } }
View Code
Interface Persondao.java:
Package Mockitodemo; Public Interface Persondao { public person Fetchperson (Integer personID); Public void Update (person person); }
View Code
Class Personservice.java:
PackageMockitodemo; Public classPersonservice {Private FinalPersondao Persondao; PublicPersonservice (Persondao Persondao) { This. Persondao =Persondao; } Public BooleanUpdate (Integer personId, String name) { person person=Persondao.fetchperson (personId); if(Person! =NULL) {person Updatedperson=NewPerson (Person.getpersonid (), name); Persondao.update (Updatedperson); return true; } Else { return false; } } }
View CodeStep 3: Add the Unit Test class.
Next, you create a unit test case for class Personservice.java. We use JUnit 4.x and Mockito 1.9.5. You can design the test case class Persionservicetest.java as follows, with a detailed note in the code:
PackageMockitodemo; ImportOrg.junit.After; ImportOrg.junit.AfterClass; ImportOrg.junit.Before; ImportOrg.junit.BeforeClass; Importorg.junit.Test; Import Staticorg.junit.assert.*; ImportOrg.mockito.Mock; Importorg.mockito.MockitoAnnotations; ImportOrg.mockito.ArgumentCaptor; Import StaticOrg.mockito.mockito.*; /*** Personservice Unit Test Case * *@authorJackzhou*/ Public classpersonservicetest {@MockPrivatePersondao Persondao;//Mock Objects PrivatePersonservice Personservice;//tested Class Publicpersonservicetest () {} @BeforeClass Public Static voidSetupClass () {} @AfterClass Public Static voidTeardownclass () {}//run before the test method that @test is labeled@Before Public voidSetUp ()throwsException {//initializes all mock objects in the test case class that are labeled by Mockito annotationsMockitoannotations.initmocks ( This); //create the object of the class under test with a mock objectPersonservice =NewPersonservice (Persondao); } @After Public voidTearDown () {} @Test Public voidShouldupdatepersonname () { person person=NewPerson (1, "Phillip"); //set the return expected value of the mock objectWhen (Persondao.fetchperson (1) . Thenreturn (person); //Perform tests BooleanUpdated = personservice.update (1, "David"); //Verify that the update is successfulasserttrue (updated); //verifies that the Fetchperson (1) method of the simulated object has been called onceVerify (Persondao). Fetchperson (1); //get a gripperargumentcaptor<person> personcaptor = Argumentcaptor.forclass (person.class); //verifies that the update () of the simulated object is called once and fetches the parameter values passed in at the callVerify (Persondao). Update (Personcaptor.capture ()); //gets the parameter value to fetchPerson Updateperson =Personcaptor.getvalue (); //parameter values when validating callsAssertequals ("David", Updateperson.getpersonname ()); //asserts that during the test, there is no other calls to the mock object. //Check if there is an unauthenticated interaction on the mock objectverifynomoreinteractions (Persondao); } @Test Public voidShouldnotupdateifpersonnotfound () {//set the return expected value of the mock objectWhen (Persondao.fetchperson (1)). Thenreturn (NULL); //Perform tests BooleanUpdated = personservice.update (1, "David"); //verifying that the update failedAssertfalse (updated); //verifies that the Fetchperson (1) method of the simulated object has been called onceVerify (Persondao). Fetchperson (1); //verifies that no interaction has occurred with the impersonated objectverifyzerointeractions (Persondao); //Check if there is an unauthenticated interaction on the mock objectverifynomoreinteractions (Persondao); } /*** Test of Update method, of class Personservice. */@Test Public voidtestupdate () {System.out.println ("Update"); Integer personId=NULL; String name= "Phillip"; Personservice instance=NewPersonservice (NewPersondao () {@Override PublicPerson Fetchperson (Integer personID) {System.out.println ("Not supported yet."); return NULL; } @Override Public voidUpdate (person person) {System.out.println ("Not supported yet."); } }); BooleanExpresult =false; Booleanresult =instance.update (personId, name); Assertequals (Expresult, result); //TODO Review the generated test code and remove the default call to fail. Fail ("The test case is a prototype.")); } }
View Code here SetupClass (), Teardownclass (), SetUp (), TearDown () is called the test fixture (Fixture), which is the Test runner (testing runner) initialized before running the test method, or later to recycle resources. Prior to JUnit 4, it was done through the setup, Teardown method. In JUnit 4, you can still initialize fields and configure the environment before each test method is run, and certainly through annotations. In JUnit 4, the Setup method is labeled by @before, and the method of labeling teardown is @After. In a test class, you can even use multiple @before to annotate multiple methods, all of which run before each test. Note that a test case class can contain multiple test methods that @test annotations, and each test method corresponds to an instance of a test case class at run time.
The @Before is initialized one time before each test method is run, and @ater is executed once after each test method has finished running. In other words, the initialization and logoff of these two annotations can guarantee the independence of each test without interfering with each other, its disadvantage is inefficient. In addition, you do not need to explicitly invoke the Initialize and purge methods in the superclass, as long as they are not overwritten, and the Test runner automatically calls these methods as needed. The @before method in the superclass is called before the @before method of the subclass (consistent with the order in which the constructor is called), @After method is that the subclass runs before the superclass. Here Shouldupdatepersonname (), Shouldnotupdateifpersonnotfound (), and testupdate () are all test Personservice's Update () methods, It relies on the Persondao interface. The first two used simulation tests. Testupdate () did not use the simulation test. Here are the test results:
Figure 4 Test Results click the Open link
As you can see, two tests using the simulation were successful, and Testupdate () failed to use the simulation test. For simulation tests, in the test case class, you first declare each of the dependent mock objects and initialize all the mock objects with Mockitoannotations.initmocks () in Setup (). When you perform a mock test, you set the return expected value of the method on the mock object, and the method on the mock object is called when the test is executed, so verify that the methods are called and that the passed parameter values are expected. For the testupdate () test, we need to create our own test personservice.update () all the Persondao data required, because we only know the public Persondao interface, its concrete implementation class (for example, to get the real data from the database, or write to a database) may be in the responsibility of another team to fit different database systems. Such dependencies undoubtedly make unit testing cumbersome, and to test with a real persondao implementation, it should also be the task of post-integration testing, integrating different components into a real-world test. With the simulation test framework, it is possible to minimize the dependency coupling during unit testing.
Mockito First Knowledge