I know that I can mock objects as follows:
Account.any_instance.expects(:type).returns("premium")
I remember hearing that this is considered a poor practice. I'd love to do something like
user = users(:bob)
user.account.expects(:type).returns("premium")
but this doesn't seem to mock the right object. Is there a better solution than using any_instance call on the class?
Edit: the error message that I'm getting is
not all expectations were satisfied
unsatisfied expectations:
- expected exactly once, not yet invoked: #<Account:0x5f9f8f8>.type(any_parameters)
I am still finding my way with mocks but have you tried something like:
account = user.account
account.expects(:type).returns("premium")
It would help to have the context of your test to know which object you wanted mocked.
Related
I have a general questions about how to treat params on a method. Let's say, we have a method that receives a number and multiplies it by 2.
def multiplier(num)
num*2
end
What happens when num is nil? Who is responsible to handle the error? The method itself or the one who calls the method? What is considered the best oop practice?
This is not related to OOP in any way, because it applies to other paradigms as well. That said, there are different schools of thought about the problem. Which one is the "best" depends on who you're talking to.
One is "defensive programming everywhere". This means each method is responsible for rigorous checks of its input.
Another is "caller is responsible for providing correct data".
Another is what I call a "security perimeter": rigorous checks only when we deal with external input, but once data is "inside of the system", it can be trusted.
And anything in between.
I agree with the other answers (#sergio-tulentsev, #Зелёный). And there is another thing to consider.
In a lot of cases it is a good practice not to expect an object of particular type, but an object which acts like a particular type. I mean, in your case, the method could expect not only a number to be passed as a parameter, but any object that could be treated like a number. That would not only make your method more powerful, but also solve the nil problem. Of course it depends on your needs.
The method version I am talking about might look like this:
def multiplier(num)
# trying to convert whatever is passed to a number
num.to_f * 2
end
In the case of nil it will return 0.0
What approach should I take to writing unit test for factories that create other objects? I've seen tests that would simply initialize two PeriodicNotifications and assert that they are equal objects. Perhaps also compare PeriodicNotification properties to the notification properties to test that PeriodicNotification parsed correctly?
They main challenge I face is knowing WHAT to test for.
The scope of a unit test can be quite modest, pretty much limited to the intent of the thing being tested. For an instance-returning class method, the unit test questions is: did I get an instance of the class initialized as I expect it to be?
The test in the OP case might be:
PumpNotification *pumpNotification = // stub object
PeriodicNotification *periodicNotification = [PeriodicNotification nodeFromNotification: pumpNotification];
// do I have an instance?
assert([periodicNotification isMemberOfClass:[PeriodicNotification self]])
assert([node[kJSON_type] isEqual:/*value from stub object*/])
// and so on for other values
I'm using RSpec's stubbing functionality to stub a where() call on an object:
allow(ActiveRecordObject).to_receive(:where).and_return(result)
This works great when the expected result is simple, such as an instance of the ActiveRecordObject with a field set to a certain value.
However, the result I want to test is more complex. I'm intending to test a value set on another ActiveRecordObject that is nested three deep through Rails hasMany functionality and this is more tricky. For example, I'd like ...
expect(result[:child_object][:test_target][:field]).to eq(value)
... to work as a test after the function that I'm testing is called.
The way I've attempted and so far failed to achieve this is by copying the structure of the object so the result is a considerably more complex.
What I'd like to do is stub the actual call (or value, if a call isn't really made) to test_target so when the call is made a much more simple stub is hit. This seems to me to be better as it creates less brittle, easier to understand code.
I've also tried stubbing a where() method on the class TestTarget.
What is the correct way to configure values in linked ActiveRecord objects in RSpec so that when the parent object is called the resulting structure contains a value hard-coded for test.
Also, is this possible without using Factory Girl (tech leads at work have decided that we want to move away from using FactoryGirl)
this blog article says that:
While there are sometimes sensible ways to mock out objects without DI
(typically by mocking out class methods, as seen in the OCMock example
above), it’s often flat out not possible. Even when it is possible,
the complexity of the test setup might outweigh the benefits. If
you’re using dependency injection consistently, you’ll find writing
tests using stubs and mocks will be much easier.
but it doesn't explain why. What are possible scenarios where DI (injecting an id object conforming to protocol) will serve better for mocking in Objective-C, than simple OCMockito:
[given([mockArray objectAtIndex:0]) willReturn:#"first"];
[verifyCount(mockArray, times(1)) objectAtIndex:];
?
I've noticed that it is easier to create a separate class for test target when the original class do some async stuff.
Let assume you write a test for UIViewController which has a LoginSystem dependency which uses AFNetworking to do a request to the API. LoginSystem takes a block argument as a callback. (UIViewController->LoginSystem->AFNetworking).
If you make a mock of LoginSystem probably you will end with problems how to fire a callback block to test your UIViewController behaviour on success/failure. When I tried that I ended with MKTArgumentCaptor to retrieve a block argument and then I had to invoke it inside a test file.
On the other hand, if you create a separate class for LoginSystem (let call it LoginSystemStub which extends from LoginSystem) you are able to "mock" a behaviour in 3 lines of code and outside the test file. We should also keep our test file clean and readable.
Another case is that verify() doesn't work with checking asynchronous behaviour. It is much more easier to call expect(smth2).will.equal(smth)
EDIT:
Pointers to NSError (NSError**) also don't work well with verify() and it's better to create a stub :D
Imagine you are trying to test a more complex behavior of an object interacting with one of its child objects. To make certain that the parent object is operating correctly, you have to mock all the methods of the child object and even potentially track its changing state.
But if you do that, you just wrote an entirely new object in a confusing and convoluted way. It would have been simpler to write an entirely new object and tell the parent to use that.
With DI you inject your model at runtime, it's not bound in your classes but only in the configuration.
When you want to mock you just create a mock model and inject that instead of your real data. Besides the model, you changed your implementation in a single line.
See here for a hands on example or here for the idea behind it.
Disclaimer: Of course you can mock other stuff than the model, but that's probably the most common use-case.
The answer is: It's not better. It's only better if you need some super custom behavior.
The best thing about it is that you don't have to create an interface/protocol for every class you inject and you can limit to DI the modules you really need to inject making your code cleaner and more YAGNI.
It applies to any dynamic language, or language with reflection. Creating so much clutter just for the sake of Unit-Tests struck me as a bad idea.
What is the difference between a mock and a stub, they both seem very similar to me?
It would be nice if someone could give a real world example of when to use which, or are they interchangeable but there is a best-practise like when to use a mock or a stub?
This is the reference in most articles, pretty generic and clear explanation:
http://martinfowler.com/articles/mocksArentStubs.html
In a nutshell:
Stubs provide canned answers to calls
made during the test, usually not
responding at all to anything outside
what's programmed in for the test.
Stubs may also record information
about calls, such as an email gateway
stub that remembers the messages it
'sent', or maybe only how many
messages it 'sent'.
And
Mocks are objects pre-programmed with
expectations which form a
specification of the calls they are
expected to receive.
The article provided and the question asked come from different contexts. Regarding the realm of Rspec, the authors of The Rspec Book write in ch 14.1:
"To create a double, just use the double() method, like this:
thingamajig_double = double('thing-a-ma-jig')
... There are also stub() and mock() methods, which produce the same kind of object:
stub_thingamajig = stub('thing-a-ma-jig')
mock_thingamajig = mock('thing-a-ma-jig')
We can use those to make the spec clearer when appropriate." (emphasis mine)
The authors also include a code snippet later in ch 14.3 -
describe Statement do
it "logs a message on generate()" do
customer = stub('customer')
customer.stub(:name).and_return('Aslak')
logger = mock('logger')
statement = Statmement.new(customer, logger)
logger.should_receive(:log).with(/Statement generated for Aslak/)
statement.generate
end
end
and then write "By using the mock() method to generate the logger double and the stub() method to generate the customer double, we're helping to express that these objects are playing different roles in the example." (emphasis mine)
These code snippets and explanations lead me to believe that while the conceptual lines drawn by Mr. Fowler in his article are good ones to draw, there is no functional difference between stub() or mock() ( or double(), for that matter) in Rspec. Could be wrong though, I haven't checked the documentation.
stub:
A fake object that returns a pre-determined value for a method call.
Actual object is not called.
Stubs and mocks often used interchangeably.
Mean two different things.
But people generally refer to "Mock Object Frameworks"
Product.stub(:find_by_title).with('orange').and_return(Product.new(:title=>"orange", :price=>6.23))
Mocks:
Just like Stubs, but with an expectation to be (or not to be) called.
Test will fail if the mock is (or isn't) called.
Used in the same way as stubs,
Product.should_receive(:find_by_title).with('orange').exactly(2).and_return(Product.new(:title=>"orange", :price=>6.23))
To know more about mock and stub please refer this article,
http://www.ibm.com/developerworks/web/library/wa-mockrails/index.html