Should I test public class function, that changes only internal state of the object? - objective-c

I decided to add unit tests to existing project (quite big one).
I am using "google toolbox for mac" for various type of STAssert... and OCMock framework.
But I think I'm testing wrong. For example, I have public function saveData, which doesn't return anything and only change internal state of the object. Should I test it? Due to encapsulation principle - I don't have to worry much about object implementation and I mustn't depend on private variables (because they can change/be deleted in the future)
#implementation Foo
-(void) saveData {
internalData_ = 88;
}
In real project this function saveData is 100 lines long and it's change a lot of private variables of the class.
So, should I test it or not? I have a little previous experience in unit testing and cannot make decision by my own.

Does the internal state that gets changed affect any later calls on that object? If so, you should include it in a unit test like
Test a()
Do saveData()
Test a() again
Even if not, it might be a good idea to unit test it. Not for determining whether other code will break by using this method, but for automatically testing the correct implementation of the method. Even though the method doesn't return anything, it probably still has some kind of contract ("If I call it, this must happen") and you should check if what should've happened, happened (e.g. a line added in a log file, or something).
Now, how to check that if the method doesn't return anything, is another question entirely. Ironically enough, that's an implementation detail of the unit test.

Related

TDD Unit Test sub-methods

I'm in a dilemma of whether I'll write tests for methods that are a product of refactoring another method.
First question, consider this plot.
class Puzzle(
val foo: List<Pieces>,
val bar: List<Pieces>
) {
init {
// code to validate foo
// code to validate bar
}
}
Here I'm validating parameters in constructing an object. This code is the result of TDD. But with TDD we write fail_test -> pass test -> refactor, when refactoring I transferred validator methods to a helper class PuzzleHelper.
object PuzzleHelper {
fun validateFoo() {
...
}
fun validateBar() {
...
}
}
Do I still need to test validateFoo and validateBar in this case?
Second question
class Puzzle(
val foo: List<Pieces>,
val bar: List<Pieces>
) {
...
fun getPiece(inPosition: Position) {
validatePosition()
// return piece at position
}
fun removePiece(inPosition: Position) {
validatePosition()
// remove piece at position
}
}
object PuzzleHelper {
...
fun validatePosition() {
...
}
}
Do I still need to write test for getPiece and removePiece that involve position validation?
I really want to be fluent in using TDD, but don't know how to start. Now I finally dive-in and don't care whats ahead, all I want is product quality. Hope to hear from your enlightenment soon.
When we get to the refactoring stage of the Red -> Green -> Refactor cycle, we're not supposed to add any new behavior. This means that all the code is already tested, so no new tests are required. You can easily validate you've done this by changing the refactored code and watch it fail a test. If it doesn't, you added something you weren't supposed to.
In some cases, if the extracted code is reused in other places, it might make sense to transfer the tests to a test suite for the refactored code.
As for the second question, that depends on your design, as well as some things that aren't in your code. For example, I don't know what you'd like to do if validation fails. You'll have to add different tests for those cases in case validation fails for each method.
The one thing I would like to point out, is that placing methods in a static object (class functions, global functions, however you want to call it) makes it harder to test code. If you'd like to test your class methods when ignoring validation (stubbing it to always pass) you won't be able to do that.
I prefer to make a collaborator that gets passed to the class as a constructor argument. So your class now gets a validator: Validator and you can pass anything you want to it in the test. A stub, the real thing, a mock, etc.
Do I still need to test validateFoo and validateBar in this case?
It depends.
Part of the point of TDD is that we should be able to iterate on the internal design; aka refactoring. That's the magic that allows us to start from a small investment in up front design and work out the rest as we go -- the fact that we can change things, and the tests evaluate the change without getting in the way.
That works really well when the required behaviors of your system are stable.
When the required behaviors of the system are not stable, when we have a lot of decisions that are in flux, when we know the required behaviors are going to change but we don't know which... having a single test that spans many unstable behaviors tends to make the test "brittle".
This was the bane of automated UI testing for a long time -- because testing a UI spans pretty much every decision at every layer of the system, tests were constantly in maintenance to eliminate cascades of false positives that arose in the face of otherwise insignificant behavior changes.
In that situation, you may want to start looking into ways introduce bulkheads that prevent excessive damage when a requirement changes. We start writing tests that validate that the test subject behaves in the same way that some simpler oracle behaves, along with a test that the simpler oracle does the right thing.
This, too, is part of the feedback loop of TDD -- because tests that span many unstable behaviors is hard, we refactor towards designs that support testing behaviors at an isolated grain, and larger compositions in terms of their simpler elements.

unit tests - white box vs. black box strategies

I found, that when I writing unit tests, especially for methods who do not return the value, I mostly write tests in white box testing manner. I could use reflection to read private data to check is it in the proper state after method execution, etc...
this approach has a lot of limitation, most important of which is
You need to change your tests if you rework method, even is API stay
the same
It's wrong from information hiding (encapsulation) point of view -
tests is a good documentation for our code, so person who will read
it could get some unnecessary info about implementation
But, if method do not return a value and operate with private data, so it's start's very hard (almost impossible) to test like with a black-box testing paradigm.
So, any ideas for a good solution in that problem?
White box testing means that you necessarily have to pull some of the wiring out on the table to hook up your instruments. Stuff I've found helpful:
1) One monolithic sequence of code, that I inherited and didn't want to rewrite, I was able to instrument by putting a state class variable into, and then setting the state as each step passed. Then I tested with different data and matched up the expected state with the actual state.
2) Create mocks for any method calls of your method under test. Check to see that the mock was called as expected.
3) Make needed properties into protected instead of private, and create a sub-class that I actually tested. The sub-class allowed me to inspect the state.
I could use reflection to read private data to check is it in the proper state after method execution
This can really be a great problem for maintenance of your test suite
in .Net instead you could use internal access modifier, so you could use the InternalsVisibleToAttribute in your class library to make your internal types visible to your unit test project.
The internal keyword is an access modifier for types and type members. Internal types or members are accessible only within files in the same assembly
This will not resolve every testing difficulty, but can help
Reference

How do you test private methods, classes, and modules?

I have looked at other discussions about this topic (on StackOverflow) however the other questions seem to be language specific whereas this is not language specific and I'm considering no longer using private methods, classes, and modules.
I want to test my private methods, classes, and modules so that I can more easily locate bugs. To allow me to do this I'm considering no longer using private methods, classes, and modules for two reasons, (1) I see no reasonable way of testing a private method, class, or module without injecting test code or using some sort of "magic" and (2) to improve code reuse. Note that I'm not considering no longer using private variables and properties because data needs protecting and does not provide behaviour therefore it does not need to be public during testing.
As a lame example, if you're writing a module called OneOperations that has two public methods addOne and subtractOne, and two private methods add and subtract. If you were not allowing yourself to have private methods you would put the two private methods into another module (basicOperations) where they are public and import those methods inside the OneOperations module. From this you should now be able to write testing code for all the methods in both modules without injecting code. An advantage of this is that the methods add and subtract can now be used in other modules by importing the basicOperations module (2 - improving code reuse).
I have a feeling this a bad idea, but I lack the real world experience to justify not doing this, which is why I've posted this question on StackOverflow.
So, how do you test your private methods, classes, and modules? Is not writing private methods, modules, and classes a potential solution?
1) Like in many other answers on this topic, the main question is why would you want to test your private methods? The purpose of a class is to provide some functionality to its clients. If you have comprehensive unit tests that prove that the public interface of this class behaves correctly, why do you care what it's doing in its private methods?
2) Your idea of not having private methods at all seems like cutting your leg off. For small projects it may be possible to have every tiny behaviour well separated and tested. But for large projects it's an overkill. What matters, is the domain logic behaving correctly.
Consider for example a method:
public double getDistanceSquared(Point other)
{
return getDifferenceSquared(this.x, other.x)
+ getDifferenceSquared(this.y, other.y);
}
private double getDifferenceSquared(double v1, double v2)
{
return (v1 - v2)*(v1 - v2);
}
Ad1) Does it really make sense to unit test getDifferenceSquared method, if getDistanceSquared returns correct results for all test cases?
Ad2) Creating a separate class for calculating squared distance between doubles - in case there is only one place when it'll be used leads to a swarm of tiny classes, with millions of tests. Also, constructors of your domain classes will accept like 10 different interfaces for every tiny thing they're doing internally.
Maintaining all this is a lot of unnecessary work. Imagine that you would like to change the method of calculating the distance (maybe use some precomputed values). The behaviour of getDistanceSquared would not change. But you would have to change all of the tests of getDifferenceSquared even though you shouldn't have to care how is the distance being calculated, as long as it's calculated correctly.
Diving into minor details when it's not necessary makes you forgot what you're really doing - you lose the "big picture view". Value your time, and focus on important problems.
As a side note, also - the main concern of unit tests is not "locating bugs" as you suggest. They impose a clean design, provide an always up-to-date documentation of your code's behaviour and allow convenient refactoring giving you flexibility. Additionally they assure you that the code is working as you expect it to.
http://artofunittesting.com/definition-of-a-unit-test/
http://en.wikipedia.org/wiki/Unit_testing#Benefits
There is another way to look at this, which is how do you generate a private method?
If we are following the TDD process properly, then the first thing we write is the test. At this point the test should contain all of our code, e.g.
public void ShouldAddTwoNumbers()
{
(1 + 1).ShouldEqual(2);
}
Yes, that looks appalling. But consider what happens as we write is some more tests.
public void ShouldAddTwoMoreNumbers()
{
(2 + 2).ShouldEqual(4);
}
Now we have something to reactor, so it can become
public void ShouldAddTwoNumbers()
{
Add(1, 1).ShouldEqual(2);
}
public void ShouldAddTwoMoreNumbers()
{
Add(2, 2).ShouldEqual(4);
}
private int Add(int a, int b)
{
return a+b;
}
So now we have a private method that we can test inside our test class. It's only when you complete further refactoring to move the code out into your application, that the private becomes an issue. Most automated refactoring tools will offer you the option of changing the methods signature at this point, so that the private method is still accessible, because its not private.
(There is a fabulous exercise called TDD as if you mean it by Keith Braithwaite which I've just paraphrased above)
However, this isn't the end of our refactorings and development. One thing that we should be doing as we write and refactor our tests is to delete old tests, for example when functionality is duplicated. Another is to extract new methods so we don't repeat ourselves. Both of these can lead to scenarios where we have private methods back in the non-test code base.
So my advice is to be pragmatic, make the best decision you can for the code that you have in front of you. I wouldn't advise not creating private methods, but I would instead look at the factors that lead you to create them.

What's the difference between a mock & stub?

I've read various articles about mocking vs stubbing in testing, including Martin Fowler's Mocks Aren't Stubs, but still don't understand the difference.
Foreword
There are several definitions of objects, that are not real. The general term is test double. This term encompasses: dummy, fake, stub, mock.
Reference
According to Martin Fowler's article:
Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
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'.
Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
Style
Mocks vs Stubs = Behavioral testing vs State testing
Principle
According to the principle of Test only one thing per test, there may be several stubs in one test, but generally there is only one mock.
Lifecycle
Test lifecycle with stubs:
Setup - Prepare object that is being tested and its stubs collaborators.
Exercise - Test the functionality.
Verify state - Use asserts to check object's state.
Teardown - Clean up resources.
Test lifecycle with mocks:
Setup data - Prepare object that is being tested.
Setup expectations - Prepare expectations in mock that is being used by primary object.
Exercise - Test the functionality.
Verify expectations - Verify that correct methods has been invoked in mock.
Verify state - Use asserts to check object's state.
Teardown - Clean up resources.
Summary
Both mocks and stubs testing give an answer for the question: What is the result?
Testing with mocks are also interested in: How the result has been achieved?
Stub
I believe the biggest distinction is that a stub you have already written with predetermined behavior. So you would have a class that implements the dependency (abstract class or interface most likely) you are faking for testing purposes and the methods would just be stubbed out with set responses. They would not do anything fancy and you would have already written the stubbed code for it outside of your test.
Mock
A mock is something that as part of your test you have to setup with your expectations. A mock is not setup in a predetermined way so you have code that does it in your test. Mocks in a way are determined at runtime since the code that sets the expectations has to run before they do anything.
Difference between Mocks and Stubs
Tests written with mocks usually follow an initialize -> set expectations -> exercise -> verify pattern to testing. While the pre-written stub would follow an initialize -> exercise -> verify.
Similarity between Mocks and Stubs
The purpose of both is to eliminate testing all the dependencies of a class or function so your tests are more focused and simpler in what they are trying to prove.
A stub is a simple fake object. It just makes sure test runs smoothly.
A mock is a smarter stub. You verify your test passes through it.
Here's a description of each one followed by with real world sample.
Dummy - just bogus values to satisfy the API.
Example: If you're testing a method of a class which requires many mandatory parameters in a constructor which have no effect on your test, then you may create dummy objects for the purpose of creating new instances of a class.
Fake - create a test implementation of a class which may have a dependency on some external infrastructure. (It's good practice that your unit test does NOT actually interact with external infrastructure.)
Example: Create fake implementation for accessing a database, replace it with in-memory collection.
Stub - override methods to return hard-coded values, also referred to as state-based.
Example: Your test class depends on a method Calculate() taking 5 minutes to complete. Rather than wait for 5 minutes you can replace its real implementation with stub that returns hard-coded values; taking only a small fraction of the time.
Mock - very similar to Stub but interaction-based rather than state-based. This means you don't expect from Mock to return some value, but to assume that specific order of method calls are made.
Example: You're testing a user registration class. After calling Save, it should call SendConfirmationEmail.
Stubs and Mocks are actually sub types of Mock, both swap real implementation with test implementation, but for different, specific reasons.
In the codeschool.com course, Rails Testing for Zombies, they give this definition of the terms:
Stub
For replacing a method with code that returns a specified result.
Mock
A stub with an assertion that the method gets called.
So as Sean Copenhaver described in his answer, the difference is that mocks set expectations (i.e. make assertions, about whether or how they get called).
Stubs don't fail your tests, mock can.
Reading all the explanations above, let me try to condense:
Stub: a dummy piece of code that lets the test run, but you don't care what happens to it. Substitutes for real working code.
Mock: a dummy piece of code that you verify is called correctly as part of the test. Substitutes for real working code.
Spy: a dummy piece of code that intercepts and verifies some calls to real working code, avoiding the need to substitute all the real code.
I think the simplest and clearer answer about this question is given from Roy Osherove in his book The art of Unit Testing (page 85)
The easiest way to tell we’re dealing with a stub is to notice that the stub can never fail the test. The asserts the test uses are always against
the class under test.
On the other hand, the test will use a mock object to verify whether the
test failed or not. [...]
Again, the mock object is the object we use to see if the test failed or not.
Stub and mock are both fakes.
If you are making assertions against the fake it means you are using the fake as a mock, if you are using the fake only to run the test without assertion over it you are using the fake as a stub.
A Mock is just testing behaviour, making sure certain methods are called.
A Stub is a testable version (per se) of a particular object.
What do you mean an Apple way?
If you compare it to debugging:
Stub is like making sure a method returns the correct value
Mock is like actually stepping into the method and making sure everything inside is correct before returning the correct value.
This slide explain the main differences very good.
*From CSE 403 Lecture 16 , University of Washington (slide created by "Marty Stepp")
To be very clear and practical:
Stub: A class or object that implements the methods of the class/object to be faked and returns always what you want.
Example in JavaScript:
var Stub = {
method_a: function(param_a, param_b){
return 'This is an static result';
}
}
Mock: The same of stub, but it adds some logic that "verifies" when a method is called so you can be sure some implementation is calling that method.
As #mLevan says imagine as an example that you're testing a user registration class. After calling Save, it should call SendConfirmationEmail.
A very stupid code Example:
var Mock = {
calls: {
method_a: 0
}
method_a: function(param_a, param_b){
this.method_a++;
console.log('Mock.method_a its been called!');
}
}
let see Test Doubles:
Fake: Fakes are objects that have working implementations, but not the same as production one. Such as: in-memory implementation of Data Access Object or Repository.
Stub: Stub is an object that holds predefined data and uses it to answer calls during tests. Such as: an object that needs to grab some data from the database to respond to a method call.
Mocks: Mocks are objects that register calls they receive.
In test assertion, we can verify on Mocks that all expected actions were performed. Such as: a functionality that calls e-mail sending service.
for more just check this.
Using a mental model really helped me understand this, rather than all of the explanations and articles, that didn't quite "sink in".
Imagine your kid has a glass plate on the table and he starts playing with it. Now, you're afraid it will break. So, you give him a plastic plate instead. That would be a Mock (same behavior, same interface, "softer" implementation).
Now, say you don't have the plastic replacement, so you explain "If you continue playing with it, it will break!". That's a Stub, you provided a predefined state in advance.
A Dummy would be the fork he didn't even use... and a Spy could be something like providing the same explanation you already used that worked.
I think the most important difference between them is their intentions.
Let me try to explain it in WHY stub vs. WHY mock
Suppose I'm writing test code for my mac twitter client's public timeline controller
Here is test sample code
twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline
STUB: The network connection to twitter API is very slow, which make my test slow. I know it will return timelines, so I made a stub simulating HTTP twitter API, so that my test will run it very fast, and I can running the test even I'm offline.
MOCK: I haven't written any of my UI methods yet, and I'm not sure what methods I need to write for my ui object. I hope to know how my controller will collaborate with my ui object by writing the test code.
By writing mock, you discover the objects collaboration relationship by verifying the expectation are met, while stub only simulate the object's behavior.
I suggest to read this article if you're trying to know more about mocks: http://jmock.org/oopsla2004.pdf
I like the explanantion put out by Roy Osherove [video link].
Every class or object created is a Fake. It is a Mock if you verify
calls against it. Otherwise its a stub.
Stub
A stub is an object used to fake a method that has pre-programmed behavior. You may want to use this instead of an existing method in order to avoid unwanted side-effects (e.g. a stub could make a fake fetch call that returns a pre-programmed response without actually making a request to a server).
Mock
A mock is an object used to fake a method that has pre-programmed behavior as well as pre-programmed expectations. If these expectations are not met then the mock will cause the test to fail (e.g. a mock could make a fake fetch call that returns a pre-programmed response without actually making a request to a server which would expect e.g. the first argument to be "http://localhost:3008/" otherwise the test would fail.)
Difference
Unlike mocks, stubs do not have pre-programmed expectations that could fail your test.
Stubs vs. Mocks
Stubs
provide specific answers to methods calls
ex: myStubbedService.getValues() just return a String needed by the code under test
used by code under test to isolate it
cannot fail test
ex: myStubbedService.getValues() just returns the stubbed value
often implement abstract methods
Mocks
"superset" of stubs; can assert that certain methods are called
ex: verify that myMockedService.getValues() is called only once
used to test behaviour of code under test
can fail test
ex: verify that myMockedService.getValues() was called once; verification fails, because myMockedService.getValues() was not called by my tested code
often mocks interfaces
I was reading The Art of Unit Testing, and stumbled upon the following definition:
A fake is a generic term that can be used to describe either a stub or a mock object (handwritten or otherwise), because they both look like the real object. Whether a fake is a stub or a mock depends on how it's used in the current test. if it's used to check an interaction (asserted against), it's a mock object. Otherwise, it's a stub.
The generic term he uses is a Test Double (think stunt double). Test Double is a generic term for any case where you replace a production object for testing purposes. There are various kinds of double that Gerard lists:
Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryTestDatabase is a good example).
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.
Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent(also called Partial Mock).
Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don't expect and are checked during verification to ensure they got all the calls they were expecting.
Source
A fake is a generic term that can be used to describe either a stub
or a mock object (handwritten or otherwise), because they both look like the
real object. Whether a fake is a stub or a mock depends on how it’s used in
the current test. If it’s used to check an interaction (asserted against), it’s a
mock object. Otherwise, it’s a stub.
Fakes makes sure test runs smoothly. It means that reader of your future test will understand what will be the behavior of the fake object, without needing to read its source code (without needing to depend on external resource).
What does test run smoothly mean?
Forexample in below code:
public void Analyze(string filename)
{
if(filename.Length<8)
{
try
{
errorService.LogError("long file entered named:" + filename);
}
catch (Exception e)
{
mailService.SendEMail("admin#hotmail.com", "ErrorOnWebService", "someerror");
}
}
}
You want to test mailService.SendEMail() method, to do that you need to simulate an Exception in you test method, so you just need to create a Fake Stub errorService class to simulate that result, then your test code will be able to test mailService.SendEMail() method. As you see you need to simulate a result which is from an another External Dependency ErrorService class.
Mocks: help to emulate and examine outcoming interactions. These interactions
are calls the SUT makes to its dependencies to change their state.
Stubs: help to emulate incoming interactions. These interactions are calls the
SUT makes to its dependencies to get input data.
source : Unit Testing Principles, Practices, and Patterns - Manning
Right from the paper Mock Roles, not Objects, by the developers of jMock :
Stubs are dummy implementations of production code that return canned
results. Mock Objects act as stubs, but also include assertions to
instrument the interactions of the target object with its neighbours.
So, the main differences are:
expectations set on stubs are usually generic, while expectations set on mocks can be more "clever" (e.g. return this on the first call, this on the second etc.).
stubs are mainly used to setup indirect inputs of the SUT, while mocks can be used to test both indirect inputs and indirect outputs of the SUT.
To sum up, while also trying to disperse the confusion from Fowler's article title: mocks are stubs, but they are not only stubs.
I came across this interesting article by UncleBob The Little Mocker. It explains all the terminology in a very easy to understand manner, so its useful for beginners. Martin Fowlers article is a hard read especially for beginners like me.
a lot of valid answers up there but I think worth to mention this form uncle bob:
https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html
the best explanation ever with examples!
A mock is both a technical and a functional object.
The mock is technical. It is indeed created by a mocking library (EasyMock, JMockit and more recently Mockito are known for these) thanks to byte code generation.
The mock implementation is generated in a way where we could instrument it to return a specific value when a method is invoked but also some other things such as verifying that a mock method was invoked with some specific parameters (strict check) or whatever the parameters (no strict check).
Instantiating a mock :
#Mock Foo fooMock
Recording a behavior :
when(fooMock.hello()).thenReturn("hello you!");
Verifying an invocation :
verify(fooMock).hello()
These are clearly not the natural way to instantiate/override the Foo class/behavior. That's why I refer to a technical aspect.
But the mock is also functional because it is an instance of the class we need to isolate from the SUT. And with recorded behaviors on it, we could use it in the SUT in the same way than we would do with a stub.
The stub is just a functional object : that is an instance of the class we need to isolate from the SUT and that's all.
That means that both the stub class and all behaviors fixtures needed during our unit tests have to be defined explicitly.
For example to stub hello() would need to subclass the Foo class (or implements its interface it has it) and to override hello() :
public class HelloStub extends Hello{
public String hello {
return "hello you!";
}
}
If another test scenario requires another value return, we would probably need to define a generic way to set the return :
public class HelloStub extends Hello{
public HelloStub(String helloReturn){
this.helloReturn = helloReturn;
}
public String hello {
return helloReturn;
}
}
Other scenario : if I had a side effect method (no return) and I would check that that method was invoked, I should probably have added a boolean or a counter in the stub class to count how many times the method was invoked.
Conclusion
The stub requires often much overhead/code to write for your unit test. What mock prevents thanks to providing recording/verifying features out of the box.
That's why nowadays, the stub approach is rarely used in practice with the advent of excellent mock libraries.
About the Martin Fowler Article : I don't think to be a "mockist" programmer while I use mocks and I avoid stubs.
But I use mock when it is really required (annoying dependencies) and I favor test slicing and mini-integration tests when I test a class with dependencies which mocking would be an overhead.
Plus useful answers, One of the most powerful point of using Mocks than Subs
If the collaborator [which the main code depend on it] is not under our control (e.g. from a third-party library),
In this case, stub is more difficult to write rather than mock.
Stub
A stub is an object that holds predefined data and uses it to answer calls during tests. It is used when you can’t or don’t want to involve objects that would answer with real data or have undesirable side effects.
An example can be an object that needs to grab some data from the database to respond to a method call. Instead of the real object, we introduced a stub and defined what data should be returned.
example of Stub:
public class GradesService {
private final Gradebook gradebook;
public GradesService(Gradebook gradebook) {
this.gradebook = gradebook;
}
Double averageGrades(Student student) {
return average(gradebook.gradesFor(student));
}
}
Instead of calling database from Gradebook store to get real students grades, you preconfigure stub with grades that will be returned. You define just enough data to test average calculation algorithm.
public class GradesServiceTest {
private Student student;
private Gradebook gradebook;
#Before
public void setUp() throws Exception {
gradebook = mock(Gradebook.class);
student = new Student();
}
#Test
public void calculates_grades_average_for_student() {
//stubbing gradebook
when(gradebook.gradesFor(student)).thenReturn(grades(8, 6, 10));
double averageGrades = new GradesService(gradebook).averageGrades(student);
assertThat(averageGrades).isEqualTo(8.0);
}
}
Mock
Mocks are objects that register calls they receive. In test assertion you can verify on Mocks that all expected actions were performed. You use mocks when you don’t want to invoke production code or when there is no easy way to verify, that intended code was executed. There is no return value and no easy way to check system state change. An example can be a functionality that calls e-mail sending service.
You don’t want to send e-mails each time you run a test. Moreover, it is not easy to verify in tests that a right email was send. Only thing you can do is to verify the outputs of the functionality that is exercised in our test. In other worlds, verify that the e-mail sending service was called.
Example of Mock:
public class SecurityCentral {
private final Window window;
private final Door door;
public SecurityCentral(Window window, Door door) {
this.window = window;
this.door = door;
}
void securityOn() {
window.close();
door.close();
}
}
You don’t want to close real doors to test that security method is working, right? Instead, you place door and window mocks objects in the test code.
public class SecurityCentralTest {
Window windowMock = mock(Window.class);
Door doorMock = mock(Door.class);
#Test
public void enabling_security_locks_windows_and_doors() {
SecurityCentral securityCentral = new SecurityCentral(windowMock, doorMock);
securityCentral.securityOn();
verify(doorMock).close();
verify(windowMock).close();
}
}
Thanks a lot to Michał Lipski for his good article. For further reading:
Test Double – Martin Fowler https://martinfowler.com/bliki/TestDouble.html
Test Double – xUnit Patterns http://xunitpatterns.com/Test%20Double.html
Mocks Aren’t Stubs – Martin Fowler https://martinfowler.com/articles/mocksArentStubs.html
Command Query Separation – Martin Fowler https://martinfowler.com/bliki/CommandQuerySeparation.html
Stub helps us to run test. How? It gives values which helps to run test. These values are itself not real and we created these values just to run the test. For example we create a HashMap to give us values which are similar to values in database table. So instead of directly interacting with database we interact with Hashmap.
Mock is an fake object which runs the test. where we put assert.
See below example of mocks vs stubs using C# and Moq framework. Moq doesn't have a special keyword for Stub but you can use Mock object to create stubs too.
namespace UnitTestProject2
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestClass]
public class UnitTest1
{
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method calls Repository GetName method "once" when Id is greater than Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Once);
}
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method doesn't call Repository GetName method when Id is Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(0);
// Assert
mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Never);
}
/// <summary>
/// Test using Stub to Verify that GetNameWithPrefix method returns Name with a Prefix
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
{
// Arrange
var stubEntityRepository = new Mock<IEntityRepository>();
stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
.Returns("Stub");
const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
var entity = new EntityClass(stubEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
}
}
public class EntityClass
{
private IEntityRepository _entityRepository;
public EntityClass(IEntityRepository entityRepository)
{
this._entityRepository = entityRepository;
}
public string Name { get; set; }
public string GetNameWithPrefix(int id)
{
string name = string.Empty;
if (id > 0)
{
name = this._entityRepository.GetName(id);
}
return "Mr. " + name;
}
}
public interface IEntityRepository
{
string GetName(int id);
}
public class EntityRepository:IEntityRepository
{
public string GetName(int id)
{
// Code to connect to DB and get name based on Id
return "NameFromDb";
}
}
}

Don't understand the purpose of behavioral tests

I'm hoping someone can help me see the real value in these tests because I read a lot about them and even worked with them on a recent project. But I never really saw the real value in the tests. Sure I can understand why they are written and see how they could sort of be useful. But it just seems that there is little ROI on these types of tests. Here is an example of some class in our code base:
class ServiceObject : IServiceObject
{
Dependency _dependency;
ServiceObject(Dependency dependency)
{
this._dependency = dependency
}
bool SomeMethod()
{
dependency.SomePublicMethod();
}
}
Then in our behavioral tests we would write test like so (pseudo code):
void ServiceObject_SomeMethod_Uses_Dependency_SomePublicMethod()
{
create mock of IServiceObject;
stub out dependency object
add expectation of call to dependency.SomePublicMethod for IServiceObject.SomeMethod
call mockserviceobject.SomeMethod
check whether expectation was satisfied
}
Obviously there are some details missing but if you are familiar with this type of testing you will understand.
So my question really derives from the fact that I can't see how it is valuable to know that my ServiceObject calls into the dependency method. I understand the reasoning behind it because you want to make sure that the logic of the method is hitting the parts that it is supposed to. But what I can't see is how this is a sustainable testing pattern?
I wrote the logic and know how the code should work so why would it ever change after I test it once to make sure that it is working? Now you can say that if you work in a team environment you might want to make sure that someone doesn't come along and change the code so that the dependency is accidentally skipped and thus would want to make sure they are aware of it. But what if it was skipped for a valid reason. Then that whole test and maybe any others would all have to be scrapped.
Anyways I am just hoping for someone to turn the light on as to the true potential of these types of tests.
The objective is to test the class in isolation, truly Unit test it. Verify that it performs exactly its responsibilities.
In this case the code is rather trivial. The value of this kind of testing may become more clear when there is conditionality in the processing path, parameters are passed to the dependency and processing is performed on the results from the dependency.
For example, suppose instead a method was like this:
bool someMethod(int paramX, int param Y ){
if ( (paramX / paramY) > 5 ){
return dependency.doOneThing(paramX);
} else {
return dependency.doSomethingElse(paramY);
}
}
Now we have quite a few tests to write, and I think the value becomes more obvious. Especially when we write a test with paramY set to zero.