Unit Test Via Visual studio-part5

Source: Internet
Author: User

This article focuses on some tips for the visual Studio (2012+) Unit Testing Framework:

    1. How to emulate a static constructor for a class
    2. How to test if a method has been called
    3. How to test the number of times a method executes
    4. Test considerations for Parallel programming
first, how to simulate the static constructor of a class1.1 code under test
namespaceblogdemo.utdemo.tricks{ Public classStaticconstructorexample {Staticstaticconstructorexample () {//step1:read data from Web service//step2:save data into database        }         Public intdosomething () {return 0; }    }}

The above class has a static constructor that does two things:

    1. Reading data from a WebService
    2. Saves the data read to the database.

Both of these things are a heavy reliance on the outside world.

We need to test the method is dosomething, need to test this class, we need to instantiate staticconstructorexample this class, before instantiating this class, its static constructor will be automatically executed: this point is the problem.

    1. Static constructors depend on the external environment, and this external environment is likely to hang up one day
    2. If the external environment hangs, the static constructor will error, and our unit test will not run as expected
    3. The dosomething itself is not directly dependent on the external environment, but indirectly relies on the external environment through a static constructor, which violates the unit test repeatable principle (when the external environment is hung, our tests will not run)

The solution is still shim, and the static constructor of a class can be simulated by Ms.test's shim, thereby altering the behavior of the static constructor and eliminating external dependencies.

1.2 test Code
[TestClass] Public classstaticconstructorexampletests {[TestMethod] Public voiddosomethingtest () {using(Shimscontext.create ()) {varisstaticconstructorexecuted =false; Shimstaticconstructorexample. StaticConstructor = () + =                {                    //Step1:mock Web Service//Step2:mock Databaseisstaticconstructorexecuted =true;                }; varExample =Newstaticconstructorexample (); vardata =example.                DoSomething (); Assert.AreEqual (0, data);            Assert.istrue (isstaticconstructorexecuted); }                   }    }

The above code is implemented by Shimclassname.staticconstructor to simulate a static constructor.

second, how to test a method has been called2.1 Code under test

Base code, calling in Democlass

     Public InterfaceIgoodactionhandler {voidAction (); }     Public InterfaceIbadactionhandler {voidAction (); }     Public classGoodhandler:igoodactionhandler { Public voidAction () {Throw Newnotimplementedexception (); }    }     Public classBadhandler:ibadactionhandler { Public voidAction () {Throw Newnotimplementedexception (); }    }

The class to be tested:

   Public classDemoClass {Igoodactionhandler goodhandler;        Ibadactionhandler Badhandler;  PublicDemoClass () { This. Goodhandler =NewGoodhandler ();  This. Badhandler =NewBadhandler (); }         Public voidDoSomething (inttype) {            if(Type = =1) {Dosomethinggood (); }            Else{Dosomethingbad (); }        }        Private voidDosomethinggood () { This. Goodhandler.action (); }        Private voidDosomethingbad () { This. Badhandler.action (); }    }

To test the DoSomething method above, both Dosomethinggood and Dosomethingbad rely on the self-interface, which can be used to mock the test. The DoSomething method on the side-test is only necessary to verify that the action of Badhandler is executed if type is 1 o'clock executed goodhandler action.

This is also a key point of unit testing: the Focus Unit . There is no concern for the internal logic of Goodhandler and Badhandler (the two handler internal logic can be tested separately and belong to another unit ), where only the logical routing to the correct handler is followed.

2.2 Test Code
[TestClass] Public classdemoclasstests {[TestMethod] Public voiddosomething_dosomethinggood_tests () {vargoodhandlerexecuted =false; Stubigoodactionhandler Goodhandler=NewStubigoodactionhandler () {Action= () + ={goodhandlerexecuted=true;//true if Goodhandler is executed                }            }; varbadhandlerexecuted =false; Stubibadactionhandler Badhandler=NewStubibadactionhandler () {Action= () + ={badhandlerexecuted=true;//true if Badhandler is executed                }            }; vardemoclass=NewDemoClass (); Democlass.badhandler=badhandler;//Inject BadhandlerDemoclass.goodhandler=goodhandler;//Inject GoodhandlerDemoclass.dosomething (1);        Assert.istrue (goodhandlerexecuted);//executed Goodhandler assert.isfalse (badhandlerexecuted);//did not execute Badhandler }    }

There are two techniques used

    1. Interface-oriented programming, using stub technology, dynamically injecting stubs (piling), simulating objects at test time
    2. Changes the behavior of the stub object, this article simply indicates whether this step was performed by setting the value of the flag bit inside the stub object.

The above flag bit method shim technique is still used, the static constructor simulation is to verify that the constructor is executed by modifying the identity bit inside the constructor after shim. The number of test executions that are introduced next is also achieved by modifying the identity bit after shim.

third, how to test the number of times a method executes3.1 code under test
   Public classDemoClass {PrivateLoophandler Handler;  PublicDemoClass () {handler=NewLoophandler (); }         Public voidDoSomething (intTimes ) {             for(vari =0; I < times; i++) {handler.            Do (); }        }    }     Public classLoophandler { Public voidDo () {}}

Now verify that DoSomething has performed the Times do method.

3.2 Test Code
[TestMethod] Public voiddosomething_runtimes_test () {using(Shimscontext.create ()) {varTimes =0; ShimLoopHandler.AllInstances.Do= (@this) = ={ times++;//Each entry is added once                }; varGiventimes = -; NewDemoClass ().                DoSomething (Giventimes);            Assert.AreEqual (Times, giventimes); }        }

The thought is the same as the above stub, and the counter is added inside the shim simulation method.

3.3 Test considerations for Parallel programming

One thing to note here is that because the INT + + is not thread-safe, the test code needs to be adjusted if the Democlass loop is modified to be executed in parallel by multiple threads. , lock the times++.

  Public voidDoSomething (intTimes ) {Parallel.For (0, Times, (item) =//Parallel Execution{handler.            Do ();        }); } [TestMethod] Public voiddosomething_runtimes_test () {using(Shimscontext.create ()) {varTimes =0; ShimLoopHandler.AllInstances.Do= (@this) = =                {                    Lock( This)//Lock Thread Safety{ times++;//Each entry is added once                    }                }; varGiventimes = -; NewDemoClass ().                DoSomething (Giventimes);            Assert.AreEqual (Times, giventimes); }        }

The above code when times are not particularly large when the general does not add lock is also possible, not particularly large when the general does not produce thread safety issues. But when the times are bigger, they can go wrong without lock.

Remove lock when times are 100000. I ran into a problem:

Testing is to be rigorous, if there is a parallel problem, the test is also a good time to add lock.

Unit Test Via Visual studio-part5

Related Article

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.