`

Unit Testing, Mocking, Stubbing and Moles?

阅读更多

As a general rule, when creating unit test, you shouldNOT have the test code communicate directly across the network, to the database, the file system, etc. This is a good thing since it will allow the unit test to be fast and remove the headache of doing test data management, etc. For more details on what a unit test should not do, see here . To achieve this goal, mocking and stubbing were introduced into the unit testing world.

Stubbing

Stubbing will allow you to create fake dependency objects that you can use to give the class that you are unit testing constant / static values, something that will not change across tests. An example of this is when you want to create a fake data repository from a data repository interface that will return you a set of pre-canned (always the same) values when queried.

var warehouse = new
 Mock<IWarehouse>();
warehouse.SetupGet(w => w.HasInventory).Returns(false
);

Fig 1. Example of a warehouse stub using Moq (warehouse stub will return false when it’s HasInventory property is invoked).

Mocking

Mocking will allow you to create fake dependency objects that contain expectations that you can validate as part of your unit test (and also can provide what stub can provide). An example of this is when you want to determine if a particular branch or path is taken when a certain parameter is passed to your method.

        [TestMethod]
        public
 void
 Should_SendMail_If_Unfilled() {
            //Assign

            var warehouse = new
 Mock<IWarehouse>();
            var mailer = new
 Mock<IMailService>();
            warehouse.SetupGet(w => w.HasInventory).Returns(false
);
            var order = new
 Order
                            {
                                ItemName = "Boo"
, 
                                Amount = 51, 
                                Mailer = mailer.Object
                            };

            //Act

            order.Fill(warehouse.Object);

            //Assert

            mailer.Verify(m => m.Send(It.IsAny<Message>()), Times.Once());

Fig 2. Example of using mock to verify mailer Send method was called once when trying to fullfill an order using Moq.

For more information on the difference between mock and stub, see this .

Perhaps this is old news, but like there are a lot of unit testing frameworks out there,i.e. NUnit , xUnit , MSTest , etc. , there are also a bunch of mocking frameworks out there, like RhinoMock , Moq , TypeMock Isolator , and recently JustMock from Telerik .

To do proper mocking or stubbing, and by extension, unit testing, you usually need the following things: interface and dependency injection.

Interface

Interface will allow you to switch one implementation of it with a different implementation. I.e. SqlRepository, that derives from an IRepository, will actually talk to a SQL database backend, while a FakeRepository that derives from the same IRepository might actually fake the database call and instead returns an in memory list of data when asked. The ability to switch between a real implementation and a fake implementation is a crucial thing if you want to make your unit test fast.

Dependency Injection

dependencyinversionprinciple_0278f9e2

Before we go too far into the topic of dependency injection, let’s take a quick detour. The Dependency Inversion Principle stated that higher level object should not depend on the lower level objects, instead, have all of them depend on a contract or interface / abstraction.

Think about how a desk lamp and electric socket interact. The electric socket can provide electricity to any devices (not just the lamp) that can connect to it. As long as the specific device that wants to get electricity implement the right plug, then it’s no problem for the socket to provide it with electricity. Compare this design versus lamps that are built into the wall and wired directly to the electrical wiring. If you want to switch the lamp, you have to tear down your wall, rip out the old lamp, install a new lamp, wire it up to the electrical wiring in the wall and redo your wall. What a pain… With electrical socket, I can just unplug the lamp and replace it with a TV for example, and it still work. The electrical socket can still provide electricity with very minimum interruption.

Again, this will allow you to easily swap one implementation with another for the same contract / interface. See here to see more detail on this topic.

public
 interface
 IElectricalDevice
{
    void
 SwitchOff();
}

public
 class
 Lamp : IElectricalDevice
{    
    public
 void
 SwitchOff()
    {
        //It's dark!

    }
}

public
 class
 Refridgerator : IElectricalDevice
{
    public
 void
 SwitchOff()
    {
       //Wow it's getting warm in here...

    }
}

public
 class
 ElectricalOutlet
{
    private
 IElectricalDevice _pluggedInDevice;
    public
 ElectricalOutlet(IElectricalDevice pluggedInDevice)
    {
        _pluggedInDevice = pluggedInDevice;
    }

    public
 void
 PowerOff()
    {
        _pluggedInDevice.SwitchOff();
    }
}

Fig 3. Example of electric socket and devices as code

Now that we see why DIP is important, comes the question of how can we “inverse” the dependency to make our solution more loosely coupled? That’s where injection comes in. You need to provide points in your object where you can inject other objects that it need to do its work.

Most common points are the class constructor and public properties. In Fig. 3 code above, I was using constructor injection in the ElectricalOutlet class (the constructor takes an IElectricalDevice object, thus injecting it into the ElectricalOutlet class). Property is self explanatory. Since you can inject different instance of object of its type during the application runtime.

Moles

mole Now, let’s talk about moles.

What a tunneling blind rodent has to do with this, you ask…

Well, not that kind of mole.

Not the other mole either (WPF debugger) . I am talking about a unit testing kind of moles. Moles is a mocking framework from Microsoft Research group with similar ability that TypeMock Isolator or JustMock offered. Just like the other products, it will allow you mock stuffs that previously unmockable if you are using mocking frameworks like RhinoMock or Moq. Unlike TypeMock and JustMock, Moles is a free product. I supposed the name was chosen due to the ability of the framework to dig deep into a class and replace whatever you wish to replace with your own implementation that you can use during unit testing.

Moles provides 2 types of capabilities: stubs and moles.

Stub is a very fast compared to moles but has certain limitation, mostly you can only stub things that has interfaces and class instances with virtual methods, similar to RhinoMock and Moq.

Mole is not as fast as stub since it injects instrumentation code into your actual classes and redirect control to itself when called. The benefit of this method is that now it can totally take control of any sealed class, static methods, etc. that are usually not mockable / stubable without a proper interface or virtual methods.

// let's detour DateTime.Now (Mole into DateTime.Now property, which usually not mockable w/ other framework)

MDateTime.Now = () => new
 DateTime(2000, 1, 1);

if
 (DateTime.Now == new
 DateTime(2000, 1, 1))
  throw
 new
 Y2KBugException(); // take cover!

Fig 4. Using Moles to return 1 Jan 2000 everytime DateTime.Now is called.

Having said that, currently Moles does not have internal mocking support like RhinoMock and Moq. To do mocking with Moles, you will have to implement them yourself.

        [TestMethod]
        [HostType("Moles"
)]
        public
 void
 Should_SendMessage_Once_When_Not_Filled() 
        {
            //Assign

            var mailSendCallCount = 0;

            //Create stubs (S prefix = stub)

            var warehouse = new
 SIWarehouse();
            var mailer = new
 SIMailService();
            
            //Setup warehouse stub to return false 

            //when its HasInventory property is called

            warehouse.HasInventoryGet = () => false
;

            //Setup mailer stub to increase the mailSendCallCount 

            //everytime SendMessage is called

            mailer.SendMessage = (m) => { mailSendCallCount++; };

            var order = new
 Order
            {
                ItemName = "Boo"
,
                Amount = 51,
                Mailer = mailer
            };

            //Act

            order.Fill(warehouse);

            //Assert

            Assert.AreEqual(1, mailSendCallCount);
        }

Fig 5. Example of mocking with Moles

Resources

To learn more detail on Moles, I suggest you check the following resources:

http://www.dimecasts.net/Casts/CastDetails/170 (good short video on introduction to Moles)

http://research.microsoft.com/en-us/projects/pex/molesmanual.pdf

Happy Unit Testing & Moling? Is that a verb?

分享到:
评论

相关推荐

    Better Unit Testing with Microsoft Fakes (RTM)

    If you are new to terms like unit testing and mocking, we still think that this guide will be useful in introducing you to these important concepts that developers need in their tool belt.

    Agile Swift(Apress,2016)

    This short step by step guide walks you through unit testing, mocking and continuous integration and how to get these key ingredients running in your Swift projects. This book also looks at how to ...

    Developer.Testing.Building.Quality.into.Software

    You’ll learn how to design for testability and utilize techniques like refactoring, dependency breaking, unit testing, data-driven testing, and test-driven development to achieve the highest ...

    Agile.Android.1484297008

    This concise book walks you through how to get unit testing and test driven development done on Android, specifically using JUnit 4. You'll learn how to do agile development quickly and correctly, ...

    Mockito Essentials(PACKT,2014)

    Whether you are new to JUnit testing and mocking or a seasoned Mockito expert, this book will provide you with the skills you need to successfully build and maintain meaningful JUnit test cases and ...

    groovy 1.6.9

    * simplifies testing by supporting unit testing and mocking out-of-the-box * seamlessly integrates with all existing Java classes and libraries * compiles straight to Java bytecode so you can use ...

    Test-Driven Java Development(PACKT,2015)

    Use mocking frameworks and techniques to easily write and quickly execute tests Develop an application to implement behaviour-driven development in conjunction with unit testing Enable and disable ...

    The.Way.of.the.Web.Tester.A.Beginners.Guide.to.Automating.Tests

    Follow the testing pyramid and level up your skills in user interface testing, integration testing, and unit testing. Your new skills will free you up to do other, more important things while letting...

    SoapUI 5.1.2 crack

    Test faster and smarter with data-driven testing, increasing your API testing coverage overnight. LEARN MORE Test Reporting Need metrics, statistics and other testing data? Get detailed, ...

    Instant Mock Testing with PowerMock.pdf

    Instant Mock Testing with PowerMock 7 Saying Hello World! (Simple) 8 Getting and installing PowerMock (Simple) 14 Mocking static methods (Simple) 22 Verifying method invocation (Simple) 28 Mocking ...

    Test-Driven Java Development - Second Edition.pdf

    Use mocking frameworks and techniques to easily write and quickly execute tests Develop an application to implement behavior-driven development in conjunction with unit testing Enable and disable ...

    soapui-eclipse-plugin 3.0 part2

    soapUI is a desktop application for inspecting, invoking, mocking and testing (functional and load) of SOAP/WSDL and REST/EADL based Web Services over ... The soapui-eclipse-plugin supports all ...

    soapui-eclipse-plugin 3.0 part3

    soapUI is a desktop application for inspecting, invoking, mocking and testing (functional and load) of SOAP/WSDL and REST/EADL based Web Services over ... The soapui-eclipse-plugin supports all ...

    soapui-eclipse-plugin 3.0 part4

    soapUI is a desktop application for inspecting, invoking, mocking and testing (functional and load) of SOAP/WSDL and REST/EADL based Web Services over ... The soapui-eclipse-plugin supports all ...

    test-driven-java-development-2nd2018

    Chapter 4, Unit Testing – Focusing on What You Do and Not on What Has Been Done, shows that to demonstrate the power of TDD applied to unit testing, we'll need to develop a remote-controlled ship. We...

    Packt Publishing Mockito Essentials (2014)

    Whether you are new to JUnit testing and mocking or a seasoned Mockito expert, this book will provide you with the skills you need to successfully build and maintain meaningful JUnit test cases and ...

    Laravel开发-laravel-dusk-mocking

    Laravel开发-laravel-dusk-mocking 拉拉维尔黄昏试验模拟立面。

    Mockito for Spring(PACKT,2015)

    This book will provide you with the skills you need to successfully build and maintain meaningful unit and integration test cases for Spring Framework code. This book starts with a brief introduction...

    Test-.Driven.Python.Development.1783987928

    Go from a unit testing beginner to a master through a series of step-by-step tutorials that are easy to follow Who This Book Is For This book is intended for Python developers who want to use the ...

    Mochito Tutorials Point

    Mockito is a mocking framework, JAVA-based library that is used for effective unit testing of JAVA applications. Mockito is used to mock interfaces so that a dummy functionality can be added to a mock...

Global site tag (gtag.js) - Google Analytics