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
Related
I have a hard time to grasp how to implement unit tests in a class where all my fields are private.
The class is calculating a user's position with BLE and CoreLocation - not that important. I have a protocol, which when a new location is found I'm calling it and all the classes which conform to that protocol will receive a room id and room name. So, what that means is that literally all the fields in my class are private, because yeah, there's no reason any outside class should access them right? But that also means I can literally test nothing in that class, even though there are quite a few functions which I would like to test. I mean, I could just make the variables internal instead of private, but it just seems wrong to do that just to unit test. I've heard about dependency injection, but it just seems like so much effort.
For example I have this function:
private var beacons: [AppBeacon] = []
private var serverBeacons:[Beacon] = []
private func addBeacons(serverBeacons: [Beacon]){
for beacon in serverBeacons {
let beacon = AppBeacon(id: beacon.id, uuid: beacon.uuid, building: beacon.building, name: beacon.name)
beacons.append(beacon)
}
}
there's no way I can test whether the beacons array was actually filled up as I wanted to or not for example. The public features of my class are basically a function called startLocating and the result which is the room id and name and I know in black box testing which unit testing imitates (right?) I should not care about the intermediate steps, but honestly, with this much functionality should I just say, doesn't matter? And assume i did populate the beacons with some rssi values of my choice, the actual location algorithm is executed on a node.js server, so I honestly don't know what to test client side?
It's classic MVC and there's no way I can change it architecture until the deadline that I have, so I don't know what's the best way to go from here? Just don't test the functionalities? Make the fields internal instead of private? We do testing of the algorithm itself server side, so testing whether the the room id is the expected room id, is already tested.
I read on another post the following:
"Unit testing by definition is black box testing, which means you don't care about the internals of the unit you test. You are mainly interested to see what's the unit output based on the inputs you give it in the unit test.
Now, by outputs we can assert on several things:
the result of a method
the state of the object after acting on it,
the interaction with the dependencies the object has
In all cases, we are interested only about the public interface, since that's the one that communicates with the rest of the world.
Private stuff don't need to have unit tests simply because any private item is indirectly used by a public one. The trick is to write enough tests that exercise the public members so that the private ones are fully covered.
Also, one important thing to keep in mind is that unit testing should validate the unit specifications, and not it's implementation. Validating implementation details adds a tight coupling between the unit testing code and the tested code, which has a big disadvantage: if the tested implementation detail changes, then it's likely that the unit test will need to be changed also, and this decreases the benefit having unit test for that piece of code."
And from that I essentially understand it as that I should just not unit test this?
If you have a private var that would help you write unit tests, change it to private(set) var so that it can be read (but not changed).
Revealing the innards may bother you. If it does, it's possible that there's another type waiting to be extracted from the view controller.
First, the definition of 'unit-test' you have quoted is quite unusual: All definitions from the literature that I am aware of consider unit-testing a glass-box/white-box testing method. More precisely, unit-testing as such is actually neither black-box or white-box - it is the method used for designing the test cases that makes the difference. But there is no reason not to apply white-box test design techniques for unit-testing. In fact, some white-box test design techniques make only sense when applied for unit-testing. For example, when you investigate on unit-testing, you will encounter a lot of discussions about different code coverage criteria, like, statement coverage, branch coverage, condition coverage, MC/DC - for all of which it is essential to know the implementation details of the code and consider these implementation details during test case design.
But, even taking that into account, it does not change much for your particular case: The variables in your code are still private :-) However, you are approaching the testing problem in a too restrictive way: You try to test the function addBeacons for itself, in total isolation even from the other functions in that component.
To test addBeacons, your test cases should not only contain a call to addBeacons, but also some other function call, the result of which would show you if the call to addBeacons was successfull. For example, if you also have a function to find a beacon by name or position, you would first call addBeacon and, to check that this has succeeded, call one of these function to see if your added beacon will be found. These two calls would be part of the same test case.
I have a method:
-(void)startTaskForResult:(long long*)result {
...
}
The function I want to unit test invoke above function:
-(void)doWork {
long long result = 0;
[self startTaskForResult:&result];
}
I am using OCMock library to do unit tests. In my test case, I want to set the result argument to an mocked value e.g. 100 without care about the actual implementation of -(void)startTaskForResult:(long long*)result.
I tried the following way:
-(void)testDoWork{
// try to set 100 to argument 'result'
OCMStub([classToTest startTaskForResult:[OCMArg setToValue:OCMOCK_VALUE((long long){100})]]);
// run the function, but it doesn't use mocked value 100 for argument 'result'
[classToTest doWork];
...
}
But, when I run my test, it does't use the mocked value 100 for argument result. What is the right way to set mocked value to argument in my case then?
Few points to answer your question:
Code for your problem:
- (void)testDoWork
{
id mock = OCMPartialMock(classToTest)
OCMStub([mock startTaskForResult:[OCMArg setToValue:OCMOCK_VALUE((long long){100})]]).andForwardToRealObject;
// set your expectation here
[classToTest doWork];
}
To solve your particular problem:
Your object should be partial mock
Your method should be stubbed (you did it)
Your stub should be forwarded to real object (i assume you need method startTaskForResult: implementation to be called)
However, you face the problems because you are using wrong approach to test;
There're 3 most common strategies to write unit tests:
Arrange-Act-Assert used to test methods
Given-When-Then used to test functions
Setup-Record-Verify used to test side effects. This usually requires mocking.
So:
If you want to test that startTaskForResult: returns particular value - you should call just that and expect return value (not your case, method return type is void)
If method changes the state of object - you should expect that state change, like property value or so
If calling of doWork has a side effect of calling startTaskForResult:, you should stub it and expect it's call, almost like i've written in code above. However (!!!), however you shouldn't expect things like this. This is not a kind of behaviour that has much sense to test, because it's internal class implementation details. One possible case, when both methods are public and it's explicitly stated in class contract, that one method should call another with some preliminary setup. In this case you expect method call with some state / arguments.
To have your application code testable, you require continuously refactoring your code. Some code is untestable, it's probably better to adopt application code rather then try to cover it with tests anyway. You lose the initial goal of tests - refactoring safety and low cost of making changes.
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.
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.
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