Monday, June 23, 2008
Flex: Anonymous Classes as Test Stubs
In my previous post, The State of Flex Testing, I stated that I use anonymous objects as stubs. This entry will show how to easily create stubs that stub methods and properties.
If you simply need a stub that has a property, the following code is all you'll need.
The above code creates an object that response with "ready" to the message
That's really it. You can define methods and properties on anonymous objects as you please.
Is it beautiful? Not really. I've considered a few other options would allow you to define methods without the anonymous function, but it's never been so annoying that it was worth spending the time to get the implementation correct. I suspect anyone who put their mind to it could come up with a nice implementation in a short amount of time.
If you simply need a stub that has a property, the following code is all you'll need.
{state: "ready"}The above code creates an object that response with "ready" to the message
state. Adding methods is also easy if you remember that you can create properties that store anonymous functions (just like Javascript). If you need the execute method to return true, the following stub should do the trick.{state: "ready", execute: function(){ return true }}That's really it. You can define methods and properties on anonymous objects as you please.
Is it beautiful? Not really. I've considered a few other options would allow you to define methods without the anonymous function, but it's never been so annoying that it was worth spending the time to get the implementation correct. I suspect anyone who put their mind to it could come up with a nice implementation in a short amount of time.
Tuesday, May 06, 2008
Using Stubs to Capture Test Essence
Back in January of 2006 I wrote about Using Stubs and Mocks to Convey Intent. In those days I was working mainly with C# and NMock and the simplest way to create a stub was to allow ReSharper generate a stub based on an Interface. This introduced a bit more effort when first generating the stub and added complexity around where the stubs should live and how they should be used. Despite the additional effort, I still felt that using them was a net gain.
Things are very different in the Ruby world. While using C#, Dependency Injection was something I used religiously; however, using Ruby I can simply stub the new method of a dependency. C# had hurdles that made stubbing controversial; however, using stubs in Ruby tests is basically seamless thanks to Mocha. Mocha makes it easy to Replace Collaborators with Stubs, but you shouldn't stop there--you should also Replace Mocks with Stubs.
Replacing Mocks with Stubs is beneficial for several reasons. Stubs are more concise. One of the largest problems with tests is that they can be overwhelming the first time you look at them. Reducing a 3 line mock definition to
Stubs are great, but you may need to use a mock to verify behavior. However, you don't need to verify several behaviors in one test. Using a single mock to verify specific behavior and stubbing all other collaborations is an easy way to create tests that focus on essence. Following the One Expectation per Test suggestion often results in using one or more stubs... and more robust tests.
Using stubs is a good first step towards concise and relevant test code; however, you can take stubs a step further. Mocha defines a
Stubs can be even more valuable if you are interested verifying a single interaction but are completely uninterested in all other interactions. In that case it's possible to define a
Since the
Lastly stubbing can help with test essence by allowing you to stub methods you don't care about. The following example defines a gateway that creates a message, sends the message, and parses the response.
The Gateway#process method is the only method that would be used by clients. In fact, it probably makes sense to make post, create_request, and parse_response private. While it's possible to test private methods, I prefer to create tests that verify what I'm concerned with and stub what I don't care about. Using partial stubbing I can always test using the public interface.
The combination of partial stubbing and defining small methods results in highly focused tests that can independently verify behavior and avoid cascading failures.
Mocha makes it as easy to define a mock as it is to define a stub, but that doesn't mean you should always prefer mocks. In fact, I generally prefer stubs and use mocks when necessary.
Things are very different in the Ruby world. While using C#, Dependency Injection was something I used religiously; however, using Ruby I can simply stub the new method of a dependency. C# had hurdles that made stubbing controversial; however, using stubs in Ruby tests is basically seamless thanks to Mocha. Mocha makes it easy to Replace Collaborators with Stubs, but you shouldn't stop there--you should also Replace Mocks with Stubs.
Replacing Mocks with Stubs is beneficial for several reasons. Stubs are more concise. One of the largest problems with tests is that they can be overwhelming the first time you look at them. Reducing a 3 line mock definition to
stub(:one => 1, :two => 2) is almost always a readability win.Stubs are great, but you may need to use a mock to verify behavior. However, you don't need to verify several behaviors in one test. Using a single mock to verify specific behavior and stubbing all other collaborations is an easy way to create tests that focus on essence. Following the One Expectation per Test suggestion often results in using one or more stubs... and more robust tests.
Using stubs is a good first step towards concise and relevant test code; however, you can take stubs a step further. Mocha defines a
stub_everything method that creates an object which will return nil to any message it doesn't understand. The stub_everything stubs are fantastic for dependencies that are used several times, but you are only interested in specific interactions. The interactions which are unimportant for the current test no longer need to be defined.Stubs can be even more valuable if you are interested verifying a single interaction but are completely uninterested in all other interactions. In that case it's possible to define a
stub_everything and set an expectation on it. Consider the following sample code.
message.from = current_user
message.timestamp
message.sent = Gateway.process(message)
end
Gateway.stubs(:process).returns(true)
message = stub_everything
message.expects(:sent=).with(true)
MessageService.deliver(message)
endSince the
expects method is defined on Object you can set expectations on concrete objects, mocks, and stubs. This results in a lot of possible combinations for defining concise behavior based tests.Lastly stubbing can help with test essence by allowing you to stub methods you don't care about. The following example defines a gateway that creates a message, sends the message, and parses the response.
response = post(create_request(message_text))
parse_response(response)
end
# ...
end
# ...
end
# ...
endThe Gateway#process method is the only method that would be used by clients. In fact, it probably makes sense to make post, create_request, and parse_response private. While it's possible to test private methods, I prefer to create tests that verify what I'm concerned with and stub what I don't care about. Using partial stubbing I can always test using the public interface.
gateway = MessageGateway.new
gateway.expects(:post).with("<text>hello world</text>")
gateway.stubs(:parse_response)
gateway.process("hello world")
end
gateway = MessageGateway.new
gateway.stubs(:create_request).returns("<text>hello world</text>")
gateway.expects(:parse_response).with("<status>success</status>")
gateway.process("")
end
gateway = MessageGateway.new
gateway.stubs(:create_request)
gateway.stubs(:post).returns("<status>success</status>")
assert_equal true, gateway.process("")
endThe combination of partial stubbing and defining small methods results in highly focused tests that can independently verify behavior and avoid cascading failures.
Mocha makes it as easy to define a mock as it is to define a stub, but that doesn't mean you should always prefer mocks. In fact, I generally prefer stubs and use mocks when necessary.
Labels: stub, Testing Refactorings
Saturday, February 02, 2008
Testing: Mocha's stub_everything method
The Mocha mocking framework provides a method, stub_everything, that returns an object that will respond 'nil' to any message sent to it. The stub_everything method is indispensable for creating an object that is needed for testing, but the interactions are completely unimportant.
For example, in the following test the ReservationService::reserve_for method needs to return a duck that responds to the same methods that are defined on the (not shown) Reservation class. However, the focus of the test has nothing to do with the behavior of the reservation duck, so stub_everything is the perfect duck because it requires no additional set up and responds to all the methods required without error.
The stub_everything method is also nice because it can take parameters. For example you may want to test that the book_for method returns a confirmation number. The following test specifies the value of the confirmation_number value, but it uses stub_everything so that each other method call will return nil (without causing an error).
Another usage of stub_everything that might not be immediately apparent is that it can be used as both a stub and a mock. The following test creates a stub and then sets an expectation on it. As a result, the expectation is verified (which is the focus of the test) and all other calls to the same object simply do nothing.
Using the stub_everything method of mocha can remove noise from tests and also make them more robust by ignoring all messages that are unimportant to the current test.
For example, in the following test the ReservationService::reserve_for method needs to return a duck that responds to the same methods that are defined on the (not shown) Reservation class. However, the focus of the test has nothing to do with the behavior of the reservation duck, so stub_everything is the perfect duck because it requires no additional set up and responds to all the methods required without error.
# implementation
end
# implementation
end
# implementation
end
reservation = ReservationService.reserve_for(customer, self)
MaidService.notify(reservation) if reservation.tomorrow?
VipService.notify(reservation) if reservation.for_vip?
reservation.confirmation_number
end
end
room = HotelRoom.new
ReservationService.expects(:reserve_for).with(:customer, room).returns(stub_everything)
room.book_for(:customer)
end
endThe stub_everything method is also nice because it can take parameters. For example you may want to test that the book_for method returns a confirmation number. The following test specifies the value of the confirmation_number value, but it uses stub_everything so that each other method call will return nil (without causing an error).
# implementation
end
# implementation
end
# implementation
end
reservation = ReservationService.reserve_for(customer, self)
MaidService.notify(reservation) if reservation.tomorrow?
VipService.notify(reservation) if reservation.for_vip?
reservation.confirmation_number
end
end
reservation = stub_everything(:confirmation_number => "confirmation number")
ReservationService.stubs(:reserve_for).returns(reservation)
assert_equal "confirmation number", HotelRoom.new.book_for(:customer)
end
endAnother usage of stub_everything that might not be immediately apparent is that it can be used as both a stub and a mock. The following test creates a stub and then sets an expectation on it. As a result, the expectation is verified (which is the focus of the test) and all other calls to the same object simply do nothing.
hotel = stub_everything
hotel.expects(:name=).with "Marriott"
Hotel.stubs(:new).returns hotel
Hotel.parse("Marriott||")
end
end
hotel = self.new
hotel.name, hotel.location, hotel.capacity = attributes.split("|")
hotel
end
endUsing the stub_everything method of mocha can remove noise from tests and also make them more robust by ignoring all messages that are unimportant to the current test.
Labels: mocha, stub, testing, Testing Refactorings
Wednesday, April 18, 2007
Ruby: Mocks and Stubs using Mocha
Update: Older versions of Mocha didn't warn when a stub was never called. The newer versions will; therefore, it makes more sense to prefer
I've previously written about using Mocks and Stubs convey intent. When I was using C#, I believed this was the best solution for creating robust tests. These days, all my code is written in Ruby. Making the switch to Ruby provided another example that reinforces an assertion I've heard before: Best Practices are so context dependent it's dangerous to use the term.
Here's the reason I no longer feel as I did when I created the above entry: When using Mocha to mock or stub behavior, I can't think of a reason I would ever want to use SomeObject.stubs(..) instead of SomeObject.expects(..). The closest I could come to a reason was that
The problem with using SomeObject.stubs is that it's almost the same as using SomeObject.expects, except if it's no longer necessary it doesn't cause a test to fail. This can lead to tests that unnecessarily stub methods as the application's implementation changes. And, the more methods that require stubbing the less the test can concisely convey intent.
I'm not asserting that you should never use SomeObject.stubs, but I do believe it's smarter to favor SomeObject.expects if you are concerned with keeping your test suite well maintained.
Of course, none of this is related to creating actual stubs for your tests. I still believe it's wise to create stub object instances for classes that are required for a unit test, but are not the class under test. For example, if I were testing a mapper class, I would use a stub for the objecting being mapped.
stub since it's less fragile and more intention revealing. I no longer feel as I did when I wrote this entry, but I've left it for historical reasons. Related reading here.I've previously written about using Mocks and Stubs convey intent. When I was using C#, I believed this was the best solution for creating robust tests. These days, all my code is written in Ruby. Making the switch to Ruby provided another example that reinforces an assertion I've heard before: Best Practices are so context dependent it's dangerous to use the term.
Here's the reason I no longer feel as I did when I created the above entry: When using Mocha to mock or stub behavior, I can't think of a reason I would ever want to use SomeObject.stubs(..) instead of SomeObject.expects(..). The closest I could come to a reason was that
stubs will allow an arbitrary number of calls to the same method. However, I don't believe that's a good enough reason since I can also use SomeObject.expects(:a_method).at_least_once.The problem with using SomeObject.stubs is that it's almost the same as using SomeObject.expects, except if it's no longer necessary it doesn't cause a test to fail. This can lead to tests that unnecessarily stub methods as the application's implementation changes. And, the more methods that require stubbing the less the test can concisely convey intent.
I'm not asserting that you should never use SomeObject.stubs, but I do believe it's smarter to favor SomeObject.expects if you are concerned with keeping your test suite well maintained.
Of course, none of this is related to creating actual stubs for your tests. I still believe it's wise to create stub object instances for classes that are required for a unit test, but are not the class under test. For example, if I were testing a mapper class, I would use a stub for the objecting being mapped.
test "an order's id is mapped to the request object" doI use a stub in the above example because I don't want to couple the test to the implementation of an order. I believe this creates a more robust, maintainable test
request = OrderServiceMapper.create_request(stub(:id=>1, ...))
assert_equal 1, request.order_id
end
Labels: mocha, mock, ruby, stub
Friday, August 11, 2006
Alternative to Dependency Injection
Generally, when a class has a dependency it is preferred to use Inversion of Control. The popular methods for specifying the dependency are setter and constructor injection. Dependency Injection is one of my favorite patterns because it facilitates loosely coupled code that is easily testable. However, recently I found an alternative solution that can be used when DI is used solely for testing.
Let's start with a class** (CellPhone) containing a dependency (SimCard):
There is an alternative solution that allows you to stub the behavior of a class without stubbing the entire class. This alternative solution is available because Ruby allows you to re-open classes. To see how this works we will need a test.
It's important to note that for our example it is assumed that CellPhone will always depend on the SimCard class. If it needed to depend on different types of SimCards then Constructor Injection would be necessary anyway.
While our solution does work it's not entirely elegant. Luckily, James Mead pointed me at Mocha, a library that facilitates this type of behavior switching. Using Stubba the test becomes much cleaner.
** Of course, the real class def would be
Let's start with a class** (CellPhone) containing a dependency (SimCard):
class CellPhoneIn this example it is not clear how you could test the CellPhone class without depending on the SimCard class. This can create problems such as the SimCard class raising errors like SimCardFullError when you are actually only trying to test the CellPhone class. A simple solution is to introduce Constructor Injection to decouple the SimCard class.
def initialize
@sim_card = SimCard.new
end
def save_number(number)
@sim_card.save_number(number)
end
def include_number?(number)
@sim_card.include_number?(number)
end
end
class CellPhoneThis solution does work; however, you now need to create an instance of the SimCard class before you can create an instance of the CellPhone class. In the case of this example additional work has been created because the CellPhone never needs to use different types of SimCards except when testing.
def initialize(sim_card)
@sim_card = sim_card
end
def save_number(number)
@sim_card.save_number(number)
end
def include_number?(number)
@sim_card.include_number?(number)
end
end
There is an alternative solution that allows you to stub the behavior of a class without stubbing the entire class. This alternative solution is available because Ruby allows you to re-open classes. To see how this works we will need a test.
class CellPhoneTest < Test::Unit::TestCaseThis test will pass with the first implementation assuming the SimCard class does not cause a problem. The change to test using the second implementation is straightforward enough that I don't feel it's necessary to demonstrate. However, what I do find interesting is how I can test CellPhone in isolation without changing the first implementation. The way to achieve this is to re-open the class within the test and alter the behavior of the class.
def test_save_number
phone = CellPhone.new.save_number('555-1212')
assert phone.include_number?('555-1212')
end
end
class CellPhoneTest < Test::Unit::TestCaseAs you can see in the example the CellPhone class tests are no longer brittle despite the dependency on SimCard.
def setup
class << SimCard
alias :save_old :save_number
alias :include_old :include_number?
def save_number(number)
end
def include_number?(number)
true
end
end
end
def teardown
class << SimCard
alias :save_number :save_old
alias :include_number? :include_old
end
end
def test_save_number
phone = CellPhone.new.save_number('555-1212')
assert phone.include_number?('555-1212')
end
end
It's important to note that for our example it is assumed that CellPhone will always depend on the SimCard class. If it needed to depend on different types of SimCards then Constructor Injection would be necessary anyway.
While our solution does work it's not entirely elegant. Luckily, James Mead pointed me at Mocha, a library that facilitates this type of behavior switching. Using Stubba the test becomes much cleaner.
require 'stubba'For more information check out the documentation for Mocha.
class CellPhoneTest < Test::Unit::TestCase
def test_save_number
SimCard.stubs(:new).returns(stub_everything(:include_number? => true))
phone = CellPhone.new.save_number('555-1212')
assert phone.include_number?('555-1212')
end
end
** Of course, the real class def would be
class CellPhone
extend Forwardable
def_delegators :@sim_card, :save_number, :include_number?
def initialize
@sim_card = SimCard.new
end
end
Labels: dependency injection, stub




