FlexMock Examples¶ ↑
RSpec.configure do |config| config.mock_with :flexmock end describe "Simple Spec" do # Simple stubbing of some methods it "stubs a couple of methods" do m = flexmock(:pi => 3.1416, :e => 2.71) m.pi.should == 3.1416 m.e.should == 2.71 end end describe "Returning Undefined" do # Create a mock object that returns an undefined object for method calls it "returns undefined values" do m = flexmock("mock") m.should_receive(:divide_by).with(0). and_return_undefined m.divide_by(0).should == FlexMock.undefined end end describe "Multiple Queries and Single Updates" do # Expect multiple queries and a single update # Multiple calls to the query method will be allows, and calls may # have any argument list. Each call to query will return the three # element array [1, 2, 3]. The call to update must have a specific # argument of 5. it "queries the db" do db = flexmock('db') db.should_receive(:query).and_return([1,2,3]) db.should_receive(:update).with(5).and_return(nil).once # Test Code db.query db.update(5) end end describe "Ordered Mocks" do # Expect all queries before any updates # All the query message must occur before any of the update # messages. it "queries and updates the database" do db = flexmock('db') db.should_receive(:query).and_return([1,2,3]).ordered db.should_receive(:update).and_return(nil).ordered # test code here db.query db.update end end describe "Ordered Mocks" do # Expect several queries with different parameters # The queries should happen after startup but before finish. The # queries themselves may happen in any order (because they are in # the same order group). The first two queries should happen exactly # once, but the third query (which matches any query call with a # four character parameter) may be called multiple times (but at # least once). Startup and finish must also happen exactly once. # Also note that we use the <code>with</code> method to match # different argument values to figure out what value to return. it "queries the database in a particular order" do db = flexmock('db') db.should_receive(:startup).once.ordered db.should_receive(:query).with("CPWR").and_return(12.3). once.ordered(:queries) db.should_receive(:query).with("MSFT").and_return(10.0). once.ordered(:queries) db.should_receive(:query).with(/^....$/).and_return(3.3). at_least.once.ordered(:queries) db.should_receive(:finish).once.ordered # Test Code db.startup db.query("MSFT") db.query("XYZY") db.query("CPWR") db.finish end end describe "Ordered Mocks" do # Same as above, but using the Record Mode interface # The record mode interface offers much the same features as the # <code>should_receive</code> interface introduced so far, but it # allows the messages to be sent directly to a recording object # rather than be specified indirectly using a symbol. it "records the queries for replay" do db = flexmock('db') db.should_expect do |rec| rec.startup.once.ordered rec.query("CPWR") { 12.3 }.once.ordered(:queries) rec.query("MSFT") { 10.0 }.once.ordered(:queries) rec.query(/^....$/) { 3.3 }.at_least.once.ordered(:queries) rec.finish.once.ordered end # Test Code db.startup db.query("MSFT") db.query("XYZY") db.query("CPWR") db.finish end end describe "Record Mode" do # Using Record Mode to record a known, good algorithm for testing # Record mode is nice when you have a known, good algorithm that can # use a recording mock object to record the steps. Then you compare # the execution of a new algorithm to behavior of the old using the # recorded expectations in the mock. For this you probably want to # put the recorder in _strict_ mode so that the recorded # expectations use exact matching on argument lists, and strict # ordering of the method calls. # <b>Note:</b> This is most useful when there are no queries on the # mock objects, because the query responses cannot be programmed # into the recorder object. it "compares a know algorithm with a new algorithm" do builder = flexmock('builder') builder.should_expect do |rec| rec.should_be_strict known_good_way_to_build_xml(rec) # record the messages end new_way_to_build_xml(builder) # compare to new way end def known_good_way_to_build_xml(builder) builder.person end def new_way_to_build_xml(builder) builder.person end end describe "Multiple Return Values" do # Expect multiple calls, returning a different value each time # Sometimes you need to return different values for each call to a # mocked method. This example shifts values out of a list for this # effect. it "returns multiple values" do file = flexmock('file') file.should_receive(:gets).with_no_args. and_return("line 1\n", "line 2\n") # test code here file.gets # returns "line 1" file.gets # returns "line 2" end end describe "Ignore Unimportant Messages" do # Ignore uninteresting messages # Generally you need to mock only those methods that return an # interesting value or wish to assert were sent in a particular # manner. Use the <code>should_ignore_missing</code> method to turn # on missing method ignoring. it "ignores unimportant messages" do m = flexmock('m') m.should_receive(:an_important_message).and_return(1).once m.should_ignore_missing # Test Code m.an_important_message m.an_unimportant_message end # When <code>should_ignore_missing</code> is enabled, ignored # missing methods will return an undefined object. Any operation on # the undefined object will return the undefined object. end describe "Partial Mocks" do # Mock just one method on an existing object # The Portfolio class calculate the value of a set of stocks by # talking to a quote service via a web service. Since we don't want # to use a real web service in our unit tests, we will mock the # quote service. it "returns the portfolio value" do flexmock(QuoteService).new_instances do |m| m.should_receive(:quote).and_return(100) end port = Portfolio.new value = port.value # Portfolio calls QuoteService.quote value.should == 100 end class QuoteService end class Portfolio def value qs = QuoteService.new qs.quote end end end