From tinney at gmail.com Thu May 1 13:38:53 2008 From: tinney at gmail.com (Dustin Tinney) Date: Thu, 1 May 2008 13:38:53 -0400 Subject: [mocha-developer] Ordered Mocking Message-ID: <41D7F960-7CB5-4756-A15E-DCE87FE52037@gmail.com> Is there any way to do ordered mocking with in mocha? And if not is there a reason, other than development time, why it isn't supported? From tinney at gmail.com Thu May 1 13:42:05 2008 From: tinney at gmail.com (Dustin Tinney) Date: Thu, 1 May 2008 13:42:05 -0400 Subject: [mocha-developer] Trapping a block Message-ID: We were trying to test this the other day and couldn't figure out if it was possible to trap the block that was being passed in: def do_something(foo) Bar.transaction do foo.baz() end end We can do an expectation on foo and an expectation on Bar but is it possible to test that foo.baz() happened inside of the Bar transaction block? Thanks... From jamesmead44 at gmail.com Thu May 1 17:41:09 2008 From: jamesmead44 at gmail.com (James Mead) Date: Thu, 1 May 2008 22:41:09 +0100 Subject: [mocha-developer] Ordered Mocking In-Reply-To: <41D7F960-7CB5-4756-A15E-DCE87FE52037@gmail.com> References: <41D7F960-7CB5-4756-A15E-DCE87FE52037@gmail.com> Message-ID: <1db558f00805011441u1ebee0bduf7234dc2b4003d65@mail.gmail.com> 2008/5/1 Dustin Tinney : > Is there any way to do ordered mocking with in mocha? And if not is there a reason, other than development time, why it isn't supported?____________________ Hi Dustin, Thanks for your interest. Please note that your emails were delayed because you had not subscribed to the list and they had to be moderated. There are a couple of ways of doing ordered mocking - sequences & states (c.f. JMock v2). These are in trunk, but have not been released yet, although I think sequences may have slipped into the v0.5.6 release by mistake (albeit undocumented). Here is the rdoc in case you are interested... sequence(name) ? sequence Returns a new sequence that is used to constrain the order in which expectations can occur. See also Expectation#in_sequence. drawing = sequence('drawing') turtle = mock('turtle') turtle.expects(:forward).with(10).in_sequence(drawing) turtle.expects(:turn).with(45).in_sequence(drawing) turtle.expects(:forward).with(10).in_sequence(drawing) states(name) ? state_machine Returns a new state machine that is used to constrain the order in which expectations can occur. See also Expectation#then, Expectation#when and StateMachine#starts_as. pen = states('pen').starts_as('up') turtle = mock('turtle') turtle.expects(:pen_down).then(pen.is('down')) turtle.expects(:forward).with(10).when(pen.is('down')) turtle.expects(:turn).with(90).when(pen.is('down')) turtle.expects(:forward).with(10).when(pen.is('down')) turtle.expects(:pen_up).then(pen.is('up')) I hope to provide a new release of Mocha very shortly. -- James. http://blog.floehopper.org http://tumble.floehopper.org From jonathan.stott at gmail.com Sat May 3 08:08:31 2008 From: jonathan.stott at gmail.com (Jonathan Stott) Date: Sat, 3 May 2008 13:08:31 +0100 Subject: [mocha-developer] Need some help in reducing my repetions in tests with Mocha Message-ID: <20080503130831.3acb25a7.jonathan.stott@gmail.com> Hi All I'm writing a gem to interact with the todoist JSON API and I'm using mocha to mock the server responses so I don't have to have a net connection to test and so I don't need to actually use my own API key anywhere. Mostly I am interested in verifying that a correctly formatted URL has been sent, with the appropriate parameters, e.g API key have been sent. So I end up with expectations like so: it "includes a token in the parameters" do http = mock() http.stubs(:use_ssl=) http.expects(:get).with { |url| url.split("?",2).last =~ /token=#{@token}/ }.returns(good_response) Net::HTTP.stubs(:new).returns(http) @base.query("viewall") end But the problem is, all my expectations basically feature the same lines of code (from http = mock() to Net::HTTP stubs) with only the "with" block changing. But because it is the with block changing, I'm not sure how to create a method which will insert my changing block into the middle of the expectation call. Well, I have a prototype method: def web_stub(good=true,&block) http = mock() http.stubs(:use_ssl=) get = http.expects(:get) if block_given? get = yield get end get.returns(good ? good_response : bad_response) Net::HTTP.stubs(:new).returns(http) end But this requires me to use the very ugly syntax of web_stub do |get| get.with do |url| url.split("?",2).first =~ /query$/ end end And I'd like to avoid the need for nested blocks if possible. Any pointers on how to implement the method, or a better way of doing it in general would be appreciated! Regards, Jon From jay at jayfields.com Sat May 3 08:49:00 2008 From: jay at jayfields.com (Jay Fields) Date: Sat, 3 May 2008 13:49:00 +0100 Subject: [mocha-developer] Need some help in reducing my repetions in tests with Mocha In-Reply-To: <20080503130831.3acb25a7.jonathan.stott@gmail.com> References: <20080503130831.3acb25a7.jonathan.stott@gmail.com> Message-ID: <41CDD529-9FF6-45F9-BD15-493B0AB98CE1@jayfields.com> Hi Jon, It's hard to give good advice because we are missing too many pieces of information. For example, your test references both @base and "good_response", neither of which are shown elsewhere. Also, without your domain code it's hard to say what the best way to test it is. But, not having enough information has never stopped me from giving my opinion before... I looks to me like you should create smaller methods, if not a few more classes depending on how much is going on. For example, you want to test that the token is in the parameters, so why not create a method that returns the url. If you have a method that returns the url, then you can test that method in isolation. On my last project I used Net::HTTP, and I understand it can be a bit of a tangled web, but I created a Gateway class that hid all the complexity of Net::HTTP from my domain. The Gateway class also had many small methods that I could test in isolation or as part of larger tests. The small methods are helpful in the larger tests because you can stub the methods you don't care about. Cheers, Jay On May 3, 2008, at 1:08 PM, Jonathan Stott wrote: > Hi All > > I'm writing a gem to interact with the todoist JSON API and I'm > using mocha to mock the server responses so I don't have to have a > net connection to test and so I don't need to actually use my own > API key anywhere. > > Mostly I am interested in verifying that a correctly formatted URL > has been sent, with the appropriate parameters, e.g API key have > been sent. So I end up with expectations like so: > > it "includes a token in the parameters" do > http = mock() > http.stubs(:use_ssl=) > http.expects(:get).with { |url| > url.split("?",2).last =~ /token=#{@token}/ > }.returns(good_response) > Net::HTTP.stubs(:new).returns(http) > @base.query("viewall") > end > > But the problem is, all my expectations basically feature the same > lines of code (from http = mock() to Net::HTTP stubs) with only the > "with" block changing. But because it is the with block changing, > I'm not sure how to create a method which will insert my changing > block into the middle of the expectation call. > > Well, I have a prototype method: > > def web_stub(good=true,&block) > http = mock() > http.stubs(:use_ssl=) > get = http.expects(:get) > if block_given? > get = yield get > end > get.returns(good ? good_response : bad_response) > Net::HTTP.stubs(:new).returns(http) > end > > But this requires me to use the very ugly syntax of > > web_stub do |get| > get.with do |url| > url.split("?",2).first =~ /query$/ > end > end > > And I'd like to avoid the need for nested blocks if possible. > > Any pointers on how to implement the method, or a better way of > doing it in general would be appreciated! > > Regards, > Jon > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer From duelin.markers at gmail.com Sat May 3 10:31:31 2008 From: duelin.markers at gmail.com (John D. Hume) Date: Sat, 3 May 2008 10:31:31 -0400 Subject: [mocha-developer] Need some help in reducing my repetions in tests with Mocha In-Reply-To: <41CDD529-9FF6-45F9-BD15-493B0AB98CE1@jayfields.com> References: <20080503130831.3acb25a7.jonathan.stott@gmail.com> <41CDD529-9FF6-45F9-BD15-493B0AB98CE1@jayfields.com> Message-ID: I'd second Jay's suggestion to have an object whose responsibility is to compose the request. You can test that without any of the noise of the Net::HTTP API. That object could also potentially expose the bits its composed to keep you from having to do something as unreadable as url.split('?', 2).last =~ /token=#{@token}/ for every parameter. Maybe one object's job is to bring together the elements of the todoist request and another's is to format requests into URLs (or with slightly broader scope, to use them to interact with Net::HTTP), so you can spec the former with lines like url.params['token'].should == @token and the other can be specified without the details of the todoist API getting in the way. -hume. On Sat, May 3, 2008 at 8:49 AM, Jay Fields wrote: > Hi Jon, > > It's hard to give good advice because we are missing too many pieces of > information. For example, your test references both @base and > "good_response", neither of which are shown elsewhere. Also, without your > domain code it's hard to say what the best way to test it is. > > But, not having enough information has never stopped me from giving my > opinion before... > > I looks to me like you should create smaller methods, if not a few more > classes depending on how much is going on. For example, you want to test > that the token is in the parameters, so why not create a method that returns > the url. If you have a method that returns the url, then you can test that > method in isolation. > > On my last project I used Net::HTTP, and I understand it can be a bit of a > tangled web, but I created a Gateway class that hid all the complexity of > Net::HTTP from my domain. The Gateway class also had many small methods that > I could test in isolation or as part of larger tests. The small methods are > helpful in the larger tests because you can stub the methods you don't care > about. > > Cheers, Jay > > > > On May 3, 2008, at 1:08 PM, Jonathan Stott wrote: > > Hi All >> >> I'm writing a gem to interact with the todoist JSON API and I'm using >> mocha to mock the server responses so I don't have to have a net connection >> to test and so I don't need to actually use my own API key anywhere. >> >> Mostly I am interested in verifying that a correctly formatted URL has >> been sent, with the appropriate parameters, e.g API key have been sent. So I >> end up with expectations like so: >> >> it "includes a token in the parameters" do >> http = mock() >> http.stubs(:use_ssl=) >> http.expects(:get).with { |url| >> url.split("?",2).last =~ /token=#{@token}/ >> }.returns(good_response) >> Net::HTTP.stubs(:new).returns(http) >> @base.query("viewall") >> end >> >> But the problem is, all my expectations basically feature the same lines >> of code (from http = mock() to Net::HTTP stubs) with only the "with" block >> changing. But because it is the with block changing, I'm not sure how to >> create a method which will insert my changing block into the middle of the >> expectation call. >> >> Well, I have a prototype method: >> >> def web_stub(good=true,&block) >> http = mock() >> http.stubs(:use_ssl=) >> get = http.expects(:get) >> if block_given? >> get = yield get >> end >> get.returns(good ? good_response : bad_response) >> Net::HTTP.stubs(:new).returns(http) >> end >> >> But this requires me to use the very ugly syntax of >> >> web_stub do |get| >> get.with do |url| >> url.split("?",2).first =~ /query$/ >> end >> end >> >> And I'd like to avoid the need for nested blocks if possible. >> >> Any pointers on how to implement the method, or a better way of doing it >> in general would be appreciated! >> >> Regards, >> Jon >> _______________________________________________ >> mocha-developer mailing list >> mocha-developer at rubyforge.org >> http://rubyforge.org/mailman/listinfo/mocha-developer >> > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > From tinney at gmail.com Sat May 3 11:31:04 2008 From: tinney at gmail.com (Dustin Tinney) Date: Sat, 3 May 2008 11:31:04 -0400 Subject: [mocha-developer] Block trap Message-ID: Sorry if this is a duplicate post. I'm trying to test this the couldn't figure out if it was possible to trap the block that was being passed in: def do_something(foo) Bar.transaction do foo.baz() end end I'd like my test to prove that foo.baz() is executed inside the block. Normally I would have written something like this: def test foo = mock("foo") trapped_block = Bar.expects(:transaction).trap target.do_something(foo) foo.expects(:baz) trapped_block.execute() end From jonathan.stott at gmail.com Sat May 3 16:23:48 2008 From: jonathan.stott at gmail.com (Jonathan Stott) Date: Sat, 3 May 2008 21:23:48 +0100 Subject: [mocha-developer] Need some help in reducing my repetions in tests with Mocha In-Reply-To: <41CDD529-9FF6-45F9-BD15-493B0AB98CE1@jayfields.com> References: <20080503130831.3acb25a7.jonathan.stott@gmail.com> <41CDD529-9FF6-45F9-BD15-493B0AB98CE1@jayfields.com> Message-ID: <20080503212348.31f2e52b.jonathan.stott@gmail.com> > Hi Jon, > > It's hard to give good advice because we are missing too many pieces > of information. For example, your test references both @base and > "good_response", neither of which are shown elsewhere. Also, without > your domain code it's hard to say what the best way to test it is. Well, a good_response is just that. It's something the library is expecting from the server (else it will raise a BadResponse error) but otherwise it isn't actually that important to the method I'm testing. (it's a stub which returns the minimum possible info) Though I've just realised perhaps I should make it a mock and actually give it some expectations when I test the net interacting part. @base is the actual thing I'm testing which has the code which makes the API request. > > But, not having enough information has never stopped me from giving my > opinion before... > > I looks to me like you should create smaller methods, if not a few > more classes depending on how much is going on. For example, you want > to test that the token is in the parameters, so why not create a > method that returns the url. If you have a method that returns the > url, then you can test that method in isolation. > There are actually some methods which are behind the query method (though not actually so fine grained/small as to have one which makes the URL) but they are currently all protected, since they should never need to be called in isolation, except if I wanted to test them ... What is the best way of testing protected methods? Or should I just make everything public? > > Cheers, Jay > Regards, Jon From jonathan.stott at gmail.com Sat May 3 16:40:46 2008 From: jonathan.stott at gmail.com (Jonathan Stott) Date: Sat, 3 May 2008 21:40:46 +0100 Subject: [mocha-developer] Need some help in reducing my repetions in tests with Mocha In-Reply-To: References: <20080503130831.3acb25a7.jonathan.stott@gmail.com> <41CDD529-9FF6-45F9-BD15-493B0AB98CE1@jayfields.com> Message-ID: <20080503214046.9de4496d.jonathan.stott@gmail.com> On Sat, 3 May 2008 10:31:31 -0400 "John D. Hume" wrote: > That object could also potentially expose the bits its composed to keep you > from having to do something as unreadable as > > url.split('?', 2).last =~ /token=#{@token}/ > > for every parameter. Well, that is mostly because I don't want to implement a full URL params parser for testing, really :) I guess it would help the clarity of the tests though. (it's just unneeded for the library as a whole, which only ever has to construct urls) > > Maybe one object's job is to bring together the elements of the todoist > request and another's is to format requests into URLs (or with slightly > broader scope, to use them to interact with Net::HTTP), so you can spec the > former with lines like > > url.params['token'].should == @token > > and the other can be specified without the details of the todoist API > getting in the way. I think I will take your and Jay's suggestion to split my method apart a little at least, even if I don't go for full on 'HttpQuery' object. Thanks, Jon From duelin.markers at gmail.com Sun May 4 09:30:05 2008 From: duelin.markers at gmail.com (John D. Hume) Date: Sun, 4 May 2008 09:30:05 -0400 Subject: [mocha-developer] Need some help in reducing my repetions in tests with Mocha In-Reply-To: <20080503214046.9de4496d.jonathan.stott@gmail.com> References: <20080503130831.3acb25a7.jonathan.stott@gmail.com> <41CDD529-9FF6-45F9-BD15-493B0AB98CE1@jayfields.com> <20080503214046.9de4496d.jonathan.stott@gmail.com> Message-ID: On Sat, May 3, 2008 at 4:40 PM, Jonathan Stott wrote: > Well, that is mostly because I don't want to implement a full URL params > parser for testing, really :) [To be clear, you wouldn't write a parser, you'd write a "builder."] I wouldn't characterize this as a design change just for testing: you're separating two responsibilities: (1) knowing how to talk to todoist, and (2) knowing how to use Net::HTTP. If todoist ever changes their api, you'll go make changes in TodoistRequestBuilder (or whatever you call that) and won't have to touch the thing that uses Net::HTTP. If instead you find an HTTP client library with more bells and whistles (or just a prettier API), you'll change your HTTP thing and won't touch the TodoistRequestBuilder. Here's a good read on the Single Responsibility Principle: http://www.objectmentor.com/resources/articles/srp.pdf From tammo at tammofreese.de Sat May 10 18:18:25 2008 From: tammo at tammofreese.de (Tammo Freese) Date: Sun, 11 May 2008 00:18:25 +0200 Subject: [mocha-developer] Mocking protected/private methods Message-ID: Hello all, I have a question concerning mocha's handling of protected and private methods. When expecting such a method, the method is public in the test. I expected the method to keep its original visibilty. Is this intended behaviour, or a bug? Thanks for your help, Tammo Freese From jamesmead44 at gmail.com Tue May 13 11:16:00 2008 From: jamesmead44 at gmail.com (James Mead) Date: Tue, 13 May 2008 16:16:00 +0100 Subject: [mocha-developer] Mocking protected/private methods In-Reply-To: References: Message-ID: <1db558f00805130816g34acfa01y5a14933ae2762440@mail.gmail.com> 2008/5/10 Tammo Freese : > I have a question concerning mocha's handling > of protected and private methods. When expecting > such a method, the method is public in the test. > > I expected the method to keep its original visibilty. > Is this intended behaviour, or a bug? It is a bug. I've had it on my own to-do list for a while, but nobody has complained about it before, so I haven't prioritised it. It would be really helpful if you could submit a proper Rubyforge bug report for it and I'll try and look at it as soon as I can. As an aside, although Mocha does provide the ability to mock private/protected methods, it's not usually a good idea, since it couples your test to the internal implementation of the class under test. Thanks. -- James. http://blog.floehopper.org http://tumble.floehopper.org From carl at carlmercier.com Tue May 20 14:50:16 2008 From: carl at carlmercier.com (Carl Mercier) Date: Tue, 20 May 2008 14:50:16 -0400 Subject: [mocha-developer] Expect with "real world" returns? Message-ID: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> Is there a way to do something like this? class Foo def self.hello(name) "Hello #{name}!" end end Foo.expects(:bar).with("Carl").once assert_equal "Hello Carl!", Foo.hello Basically, my problem is that once you set an expectation, the original code is never executed and is not tested. However, it's still very useful to set expectations to make sure the right arguments are passed to certain methods. The above example surely is over simplistic, but in a real world scenario, it totally makes sense. Is it possible to do something like this in Mocha as it is right now. If not, is that something you'd consider implementing? Thanks! /carl From duncanbeevers at gmail.com Tue May 20 17:55:01 2008 From: duncanbeevers at gmail.com (Duncan Beevers) Date: Tue, 20 May 2008 14:55:01 -0700 Subject: [mocha-developer] Expect with "real world" returns? In-Reply-To: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> References: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> Message-ID: <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> Brian Takita discusses this functionality in his RR mocking framework under the moniker Mock Proxy. http://pivots.pivotallabs.com/users/brian/blog/articles/352-introducing-rr Not sure if I've posted to this about the pattern before, but it looks really useful, especially if it could be combined with traditional mocking techniques. On Tue, May 20, 2008 at 11:50 AM, Carl Mercier wrote: > Is there a way to do something like this? > > class Foo > def self.hello(name) > "Hello #{name}!" > end > end > > Foo.expects(:bar).with("Carl").once > > assert_equal "Hello Carl!", Foo.hello > > Basically, my problem is that once you set an expectation, the original code > is never executed and is not tested. However, it's still very useful to set > expectations to make sure the right arguments are passed to certain methods. > The above example surely is over simplistic, but in a real world scenario, > it totally makes sense. > > Is it possible to do something like this in Mocha as it is right now. If > not, is that something you'd consider implementing? > > Thanks! > > /carl > > > > > > > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer > From carl at carlmercier.com Wed May 21 10:56:40 2008 From: carl at carlmercier.com (Carl Mercier) Date: Wed, 21 May 2008 10:56:40 -0400 Subject: [mocha-developer] Expect with "real world" returns? In-Reply-To: <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> References: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> Message-ID: <950923D6-A6EF-432F-8768-D623503C4436@carlmercier.com> I wish Mocha supported this "out of the box" with this syntax: User.expects(:find).with(1) # returns the "real" row from the database User.expects(:find).with(1).returns(mocked_row) # returns a fake row and to have something explicitly return nil (without running the real code): Foo.expects(:bar).returns(nil) It's probably too late to change the way .expects work right now, however. /c On 20-May-08, at 5:55 PM, Duncan Beevers wrote: > Brian Takita discusses this functionality in his RR mocking framework > under the moniker Mock Proxy. > > http://pivots.pivotallabs.com/users/brian/blog/articles/352-introducing-rr > > Not sure if I've posted to this about the pattern before, but it looks > really useful, especially if it could be combined with traditional > mocking techniques. From zach.lists at gmail.com Wed May 21 16:32:38 2008 From: zach.lists at gmail.com (Zach Moazeni) Date: Wed, 21 May 2008 16:32:38 -0400 Subject: [mocha-developer] Expect with "real world" returns? In-Reply-To: <950923D6-A6EF-432F-8768-D623503C4436@carlmercier.com> References: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> <950923D6-A6EF-432F-8768-D623503C4436@carlmercier.com> Message-ID: On May 21, 2008, at 10:56 AM, Carl Mercier wrote: > I wish Mocha supported this "out of the box" with this syntax: > > User.expects(:find).with(1) # returns the "real" row from the > database > User.expects(:find).with(1).returns(mocked_row) # returns a fake row In my opinion, I don't find that useful. If I want the real row from the database to brought in, I wouldn't use mocking. I only use expects / stubs when I want to alter and/or assert behavior. > and to have something explicitly return nil (without running the > real code): > Foo.expects(:bar).returns(nil) I'm too lazy to check right now, but I thought that was the current behavior. Foo.expects(:bar) Foo.bar => nil From carl at carlmercier.com Wed May 21 16:35:21 2008 From: carl at carlmercier.com (Carl Mercier) Date: Wed, 21 May 2008 16:35:21 -0400 Subject: [mocha-developer] Expect with "real world" returns? In-Reply-To: References: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> <950923D6-A6EF-432F-8768-D623503C4436@carlmercier.com> Message-ID: I think you missed my point. I -do- want the real database row, but I also want to make sure that the "find" method is called with the right parameters and x number of times. So this is not really mocking, just setting expectations about what will be called and with what arguments. On 21-May-08, at 4:32 PM, Zach Moazeni wrote: > On May 21, 2008, at 10:56 AM, Carl Mercier wrote: > >> I wish Mocha supported this "out of the box" with this syntax: >> >> User.expects(:find).with(1) # returns the "real" row from the >> database >> User.expects(:find).with(1).returns(mocked_row) # returns a fake row > > In my opinion, I don't find that useful. If I want the real row from > the database to brought in, I wouldn't use mocking. I only use > expects / stubs when I want to alter and/or assert behavior. > >> and to have something explicitly return nil (without running the >> real code): >> Foo.expects(:bar).returns(nil) > > I'm too lazy to check right now, but I thought that was the current > behavior. > > Foo.expects(:bar) > Foo.bar => nil > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer From justinwr at gmail.com Wed May 21 16:51:23 2008 From: justinwr at gmail.com (Justin Reagor) Date: Wed, 21 May 2008 16:51:23 -0400 Subject: [mocha-developer] Expect with "real world" returns? In-Reply-To: References: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> <950923D6-A6EF-432F-8768-D623503C4436@carlmercier.com> Message-ID: <656434FC-1FF2-4D94-A80C-0C4DAC708E78@gmail.com> > So this is not really mocking, just setting expectations about what > will be called and with what arguments. Isn't that the current functionality though? If I do a... Model.expects(:find).with(:all, {:conditions => ['id = ?', 1]}).returns(@model) I get the arguments tested because Model.find(:all) would fail and tell me I forgot the :conditions hash. Now I do understand that the return value would not be tested by Mocha against what I provided... but if I'm testing return values I would just do. @model.should_not be_nil :: Justin Reagor :: justinwr at gmail.com On May 21, 2008, at 4:35 PM, Carl Mercier wrote: > I think you missed my point. I -do- want the real database row, > but I also want to make sure that the "find" method is called with > the right parameters and x number of times. > > So this is not really mocking, just setting expectations about what > will be called and with what arguments. > > On 21-May-08, at 4:32 PM, Zach Moazeni wrote: > >> On May 21, 2008, at 10:56 AM, Carl Mercier wrote: >> >>> I wish Mocha supported this "out of the box" with this syntax: >>> >>> User.expects(:find).with(1) # returns the "real" row from the >>> database >>> User.expects(:find).with(1).returns(mocked_row) # returns a fake >>> row >> >> In my opinion, I don't find that useful. If I want the real row >> from the database to brought in, I wouldn't use mocking. I only >> use expects / stubs when I want to alter and/or assert behavior. >> >>> and to have something explicitly return nil (without running the >>> real code): >>> Foo.expects(:bar).returns(nil) >> >> I'm too lazy to check right now, but I thought that was the >> current behavior. >> >> Foo.expects(:bar) >> Foo.bar => nil >> >> _______________________________________________ >> mocha-developer mailing list >> mocha-developer at rubyforge.org >> http://rubyforge.org/mailman/listinfo/mocha-developer > > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer From zach.lists at gmail.com Wed May 21 16:54:36 2008 From: zach.lists at gmail.com (Zach Moazeni) Date: Wed, 21 May 2008 16:54:36 -0400 Subject: [mocha-developer] Expect with "real world" returns? In-Reply-To: References: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> <950923D6-A6EF-432F-8768-D623503C4436@carlmercier.com> Message-ID: <085AD41F-C6F6-4DE1-9F5A-E47C25E149F4@gmail.com> On May 21, 2008, at 4:35 PM, Carl Mercier wrote: > I think you missed my point. I -do- want the real database row, but > I also want to make sure that the "find" method is called with the > right parameters and x number of times. I'll chalk it up to different testing strategies using mocking, but to my recollection, I've never come across the need for my code to execute real code as well as assert the parameters and number of times the function was called. But I'm speaking from my experience, and my needs which are most likely different from yours. If I'm concerned with the parameters, I'll stub or expect it (depending on the situation), and return either an existing object or stub. But even when I'm testing ActiveRecord, I rarely send back an instance of an ActiveRecord object. If the code under test requires a real instance, and can't succinctly use a stub, it starts to smell as if the code is doing too much to that instance. Another thing to note, is that I'm a big fan of returning literals when behavior is not required on the return value itself. Car.stubs(:find).with(1).returns("the car") Car.stubs(:find).with(:all, :conditions => ["color = ?", "red"]).returns(["car 1", "car 2"]) This is very useful, and readable, when the return becomes a parameter for another function, or the return is used in an algorithm (like reversing an array). -Zach From carl at carlmercier.com Wed May 21 22:29:18 2008 From: carl at carlmercier.com (Carl Mercier) Date: Wed, 21 May 2008 22:29:18 -0400 Subject: [mocha-developer] Expect with "real world" returns? In-Reply-To: <656434FC-1FF2-4D94-A80C-0C4DAC708E78@gmail.com> References: <4D982B17-A8C7-4AE4-96CB-378B00635633@carlmercier.com> <6a2b4fd00805201455w7bec600n7fe845ddf22dfef6@mail.gmail.com> <950923D6-A6EF-432F-8768-D623503C4436@carlmercier.com> <656434FC-1FF2-4D94-A80C-0C4DAC708E78@gmail.com> Message-ID: Here's a test file to illustrate what I'm saying. #------------- require File.dirname(__FILE__) + "/../test_helper" class BlehTest < Test::Unit::TestCase def foo(x) "bar #{x}" end def test_foo # fails, foo(1) returns nil # ideally, this test should pass and execute the foo # method since I didn't specify a return value self.expects(:foo).with(1) assert_equal "bar 1", foo(1) end def test_foo2 # fails, foo(1) returns nil, foo is already mocked, # so totally understandable self.expects(:foo).with(1).returns(foo(1)) assert_equal "bar 1", foo(1) end def test_foo3 # works, but verbose and not very dry. very tricky # to do something like this in a real world scenario output = foo(1) self.expects(:foo).with(1).returns(output) assert_equal "bar 1", foo(1) # success end end #------------- On 21-May-08, at 4:51 PM, Justin Reagor wrote: >> So this is not really mocking, just setting expectations about what >> will be called and with what arguments. > > > Isn't that the current functionality though? From rick at calicojack.co.uk Wed May 28 11:12:34 2008 From: rick at calicojack.co.uk (Rick Moynihan) Date: Wed, 28 May 2008 16:12:34 +0100 Subject: [mocha-developer] Mocking objects to test Rails Controllers Message-ID: <483D7662.6060702@calicojack.co.uk> Hi all, I'm currently considering the use of Mocha to aid in writing my Rails unit/functional tests. I currently have a Rails model which mixes in a series of methods to allow it to talk to an external service. The code is roughly of this form: class Person < ActiveRecord::Base include SMSNotifier def send_notification(message) send_sms(number,message) # more code/interactions... end end Assuming I want to test that a call to send_notification calls send_sms on the SMSNotifier module, what is the best way to use Mocha to do this? Obviously I don't want my tests calls to send_notification to actually do any SMS sending :-) I'm assuming Mocha can monkey-patch it's own method/expectations over the SMSNotifier module. In Java, I'd use dependency injection, but I'm trying to find the Ruby way here. Also I've seen that Rails has a folder called test/mocks, can anyone provide any examples or links as to the use of this in Rails/Mocha? Thanks in advance for your assistance, R. From rsanheim at gmail.com Wed May 28 11:29:41 2008 From: rsanheim at gmail.com (Rob Sanheim) Date: Wed, 28 May 2008 11:29:41 -0400 Subject: [mocha-developer] Mocking objects to test Rails Controllers In-Reply-To: <483D7662.6060702@calicojack.co.uk> References: <483D7662.6060702@calicojack.co.uk> Message-ID: On Wed, May 28, 2008 at 11:12 AM, Rick Moynihan wrote: > Hi all, > > I'm currently considering the use of Mocha to aid in writing my Rails > unit/functional tests. > > I currently have a Rails model which mixes in a series of methods to allow > it to talk to an external service. The code is roughly of this form: > > class Person < ActiveRecord::Base > > include SMSNotifier > > def send_notification(message) > send_sms(number,message) > # more code/interactions... > end > end > > Assuming I want to test that a call to send_notification calls send_sms on > the SMSNotifier module, what is the best way to use Mocha to do this? > Obviously I don't want my tests calls to send_notification to actually do > any SMS sending :-) > > I'm assuming Mocha can monkey-patch it's own method/expectations over the > SMSNotifier module. In Java, I'd use dependency injection, but I'm trying > to find the Ruby way here. > > Also I've seen that Rails has a folder called test/mocks, can anyone provide > any examples or links as to the use of this in Rails/Mocha? > > Thanks in advance for your assistance, With mocha, this is very simple. Say goodbye to DI, and forget the builtin rails/mocks as well. def test_sends_sms_with_number person = Person.new(:number => "5551234567") person.expects(:send_sms).with("5551234567", "test msg") person.send_notification("test msg") end That test will ensure your sms method gets called, and it also removes its implementation so no actual web service calls are made. - Rob http://robsanheim.com http://thinkrelevance.com From andrew at avit.ca Wed May 28 14:16:30 2008 From: andrew at avit.ca (Andrew Vit) Date: Wed, 28 May 2008 11:16:30 -0700 Subject: [mocha-developer] Mocking objects to test Rails Controllers In-Reply-To: References: <483D7662.6060702@calicojack.co.uk> Message-ID: <54A5B018-08F6-445A-9840-BE7574EF326A@avit.ca> I think Rick was asking how to test from a controller. Assuming that the controller intantiates the Person object so you can't setup with Person.new inside your test, you can do: Person.any_instance.expects(:send_sms) --Andrew Vit On May 28, 2008, at 8:29 AM, Rob Sanheim wrote: > On Wed, May 28, 2008 at 11:12 AM, Rick Moynihan > wrote: >> Hi all, >> >> I'm currently considering the use of Mocha to aid in writing my Rails >> unit/functional tests. >> >> I currently have a Rails model which mixes in a series of methods >> to allow >> it to talk to an external service. The code is roughly of this form: >> >> class Person < ActiveRecord::Base >> >> include SMSNotifier >> >> def send_notification(message) >> send_sms(number,message) >> # more code/interactions... >> end >> end >> >> Assuming I want to test that a call to send_notification calls >> send_sms on >> the SMSNotifier module, what is the best way to use Mocha to do this? >> Obviously I don't want my tests calls to send_notification to >> actually do >> any SMS sending :-) >> >> I'm assuming Mocha can monkey-patch it's own method/expectations >> over the >> SMSNotifier module. In Java, I'd use dependency injection, but I'm >> trying >> to find the Ruby way here. >> >> Also I've seen that Rails has a folder called test/mocks, can >> anyone provide >> any examples or links as to the use of this in Rails/Mocha? >> >> Thanks in advance for your assistance, > > With mocha, this is very simple. Say goodbye to DI, and forget the > builtin rails/mocks as well. > > def test_sends_sms_with_number > person = Person.new(:number => "5551234567") > person.expects(:send_sms).with("5551234567", "test msg") > person.send_notification("test msg") > end > > That test will ensure your sms method gets called, and it also removes > its implementation so no actual web service calls are made. > > - Rob > > http://robsanheim.com > http://thinkrelevance.com > _______________________________________________ > mocha-developer mailing list > mocha-developer at rubyforge.org > http://rubyforge.org/mailman/listinfo/mocha-developer From rick at calicojack.co.uk Thu May 29 12:41:52 2008 From: rick at calicojack.co.uk (Rick Moynihan) Date: Thu, 29 May 2008 17:41:52 +0100 Subject: [mocha-developer] Mocking objects to test Rails Controllers In-Reply-To: <54A5B018-08F6-445A-9840-BE7574EF326A@avit.ca> References: <483D7662.6060702@calicojack.co.uk> <54A5B018-08F6-445A-9840-BE7574EF326A@avit.ca> Message-ID: <483EDCD0.9010505@calicojack.co.uk> Andrew Vit wrote: > I think Rick was asking how to test from a controller. Assuming that > the controller intantiates the Person object so you can't setup with > Person.new inside your test, you can do: > > Person.any_instance.expects(:send_sms) Thanks for this Andrew. You were right about what I was asking, but Rob's answer gave me enough courage to dive in, and find it pretty much just worked as expected. I had my code mocked and tested (to some degree) within 5 minutes. Yay Mocha! :-) R.