@@ -48,6 +48,9 @@ Enhancements:. Change argument matchers to use `` as their primary matchingprotocol, as their semantics mirror that of a case or rescue statement(which uses `` for matching). (Myron Marston). Add `RSpec::Mocks.withtemporaryscope`, which allows you to createtemporary rspec-mocks scopes in arbitrary places (such as a`before(:all)` hook). (Myron Marston)### 3.0.0.beta1 / 2013-11-07 full changelog(http://github.com/rspec/rspec-mocks/compare/v2.99.0.beta1.v3.0.0.beta1).
![Rspec expect exception Rspec expect exception](https://assets.devhints.io/previews/rspec.jpg?t=20190430045654)
Invitation = spy( 'invitation ')user.acceptinvitation(invitation)expect(invitation).to havereceived(:accept)# You can also use other common message expectations. For example:expect(invitation).to havereceived(:accept).with(mailer)expect(invitation).to havereceived(:accept).twiceexpect(invitation).tonot havereceived(:accept).with(mailer)# One can specify a return value on the spy the same way one would a double.invitation = spy( 'invitation ',:accept = true)expect(invitation).to havereceived(:accept).with(mailer)expect(invitation.accept).to eq( true)Note that havereceived(.).with(.) is unable to work properly whenpassed arguments are mutated after the spy records the received message.For example, this does not work properly. Greeter = spy( 'greeter ')message = 'Hello 'greeter.greetwith(message)message. Expect(double).to receive(:msg).with( 'A ', 1, 3)expect(double).to receive(:msg).with( 'B ', 2, 4) Argument MatchersArguments that are passed to with are compared with actual argumentsreceived using.
RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using.
In cases in which you want to specify things about thearguments rather than the arguments themselves, you can use any of thematchers that ship with rspec-expectations. They don't all make syntacticsense (they were primarily designed for use with RSpec::Expectations), butyou are free to create your own custom RSpec::Matchers.rspec-mocks also adds some keyword Symbols that you can use tospecify certain kinds of arguments. Expect(double).to receive(:msg).onceexpect(double).to receive(:msg).twiceexpect(double).to receive(:msg).exactly(n).timeexpect(double).to receive(:msg).exactly(n).timesexpect(double).to receive(:msg).atleast(:once)expect(double).to receive(:msg).atleast(:twice)expect(double).to receive(:msg).atleast(n).timeexpect(double).to receive(:msg).atleast(n).timesexpect(double).to receive(:msg).atmost(:once)expect(double).to receive(:msg).atmost(:twice)expect(double).to receive(:msg).atmost(n).timeexpect(double).to receive(:msg).atmost(n).times Ordering. Expect(double).to receive(:msg).andreturn(value)expect(double).to receive(:msg).exactly( 3).times.andreturn(value1, value2, value3)# returns value1 the first time, value2 the second, etcexpect(double).to receive(:msg).andraise(error)# `error` can be an instantiated object (e.g. `StandardError.new(somearg)`) or a class (e.g.
`StandardError`) # if it is a class, it must be instantiable with no argsexpect(double).to receive(:msg).andthrow(:msg)expect(double).to receive(:msg).andyield(values, to, yield)expect(double).to receive(:msg).andyield(values, to, yield).andyield(some, other, values, this, time)# for methods that yield to a block multiple timesAny of these responses can be applied to a stub as well. Allow(double).to receive(:msg).andreturn(value)allow(double).to receive(:msg).andreturn(value1, value2, value3)allow(double).to receive(:msg).andraise(error)allow(double).to receive(:msg).andthrow(:msg)allow(double).to receive(:msg).andyield(values, to, yield)allow(double).to receive(:msg).andyield(values, to, yield).andyield(some, other, values, this, time) Arbitrary HandlingOnce in a while you'll find that the available expectations don't solve theparticular problem you are trying to solve. Imagine that you expect the messageto come with an Array argument that has a specific length, but you don't carewhat is in it. You could do this. Expect(double).to receive(. Allowanyinstanceof( Widget).to receive(:name).andreturn( 'Wibble ')expectanyinstanceof( Widget).to receive(:name).andreturn( 'Wobble ')These methods add the appropriate stub or expectation to all instances ofWidget.This feature is sometimes useful when working with legacy code, though ingeneral we discourage its use for a number of reasons:. The rspec-mocks API is designed for individual object instances, but thisfeature operates on entire classes of objects.
As a result there are somesemantically confusing edge cases. For example inexpectanyinstanceof(Widget).to receive(:name).twice it isn't clearwhether each specific instance is expected to receive name twice, or if tworeceives total are expected. (It's the former.).
Using this feature is often a design smell. It may bethat your test is trying to do too much or that the object under test is toocomplex. It is the most complicated feature of rspec-mocks, and has historicallyreceived the most bug reports. (None of the core team actively use it,which doesn't help.)Further ReadingThere are many different viewpoints about the meaning of mocks and stubs. Ifyou are interested in learning more, here is some recommended reading:. Mock Objects:. Endo-Testing:.
Mock Roles, Not Objects:. Test Double:. Test Double Patterns:. Mocks aren't stubs:Also see.