I have a question concerning unit testing.
I have to test a function, call it function A, that receives as input an instance of a class B, and returns true or false.
Now in my test I have to somehow create an object to pass to the function A; what I'm currently doing is to initialize the class B using its constructor and calling some of its methods to populate it, create the right structures, etc. and then pass it to the function A. Now, I'm not sure that this is a good pattern: in particular what happens if there's a bug in one the methods of class B, or I change its interface?
So I guess I would need to use a stub; but it seems weird to write a class that has basically the same structures of my class B; also the function A will ultimately work with the class B, so if I change the interface of class B then the test for function A should crash to tell me to change function A to accommodate the new interface.
What is the correct pattern to use?
NOTE: If you think this is primarily opinion based, please reformulate the question as: "According to the principles advocated in "The Art of Unit Testing", what would be the best thing to do here?" - for the rest of you who are sane, feel free to write an answer with a larger perspective
Edit
I should clarify, the sole purpose of function A is to take an instance of class B and verify that a certain condition is met. Now, I could create a stub in place of class B, but I am not sure this would make sense; it seems rather pointless. On the other hand to initialize B I do something like classB.addData(randomData); what happens if this code fails? I will get an error in the test for function A while the actual problem is in the initialization of class B
Edit 2
Some code that shows more explicitly what the function does. The real code is exactly the same, except the methods are more complicated but otherwise it's exactly the same
def functionA(objectB):
return objectB.data < 10
def testFunctionA():
objectB = classB()
objectB.addData(19) #Is this a problem or should I stub objectB?
assert(functionA(objectB) is False)
In my opinion, the most powerful tool in the unit testing toolbox is dependency injection, and that fits perfectly here.
When constructing an object, all its collaborator objects should be passed to its constructor in the form of interface references. In your case the unit to be tested is a function, but the principle is the same. The functions collaborator objects are passed to it in the same manner.
If your test object only collaborates with other objects through interfaces, it is possible to pass mock objects in unit testing. Also, frameworks like google mock makes it very convenient to create mocks, and write clean test cases where the expected interactions are easy to understand.
If this is what you meant, then yes, that is a good pattern.
Edit:
This is how i would write the test function.
def functionA(objectB):
return objectB.data < 10
def testFunctionA():
objectB = fakeClassB()
EXPECT_CALL(objectB, data).WillOnce(Return(19))
assert(functionA(objectB) is False)
Instead of passing a real classB object, pass a fakeClassB object. This makes the test depending on the interface of classB rather than the actual implementation of classB. A failing test is caused by a faulty use of the interface and not some implementation detail n classB. Depending on what language you are working with, this could be possible or not i suppose.
Another perk is build complexity. You can build the test function without building the implementation of classB. You only need to build the interface of classB and the fakeClassB.
There is a rule in testing: mock all units other than the tested one. The point of mocking is to provide some correct output values when you would call units that are used in the tested unit. You should explicitly provide some samples that you know are correct, so that the tested unit can not fail because of some fail caused of the unit used by it.
Too long for a comment:
in the scope of unit testing A, Bs implementation should not matter. Using a mock/stub/whatever in order to test the different branches of A is fine.
If Bs implementation at some point changes, that should not matter in regards to As implementation (in an ideal scenario, but your example is very abstract). If Bs implementation were to be significantly changed in so much that A is looking at different members of B, then yes, you could have an impact to As unit tests. If Bs implementation of arriving at the members that A relies on changes, that will not matter with a mocked version of B.
It will however matter to Bs unit tests.
If you have anything concrete I can elaborate, but right now it's mostly just an abstract answer for an abstract question.
def functionA(objectB):
return objectB.data < 10
def testFunctionA():
objectB = classB()
objectB.addData(19) #Is this a problem or should I stub objectB?
assert(functionA(objectB) is False)
is this python? I don't know python, but I'm guessing functionA returns true when objectB.data lt 10, and false otherwise.
Given all of that, functionA is still only returning a true or false based on a member of objectB. How objectB.data gets its data is not relevant to the scope of unit testing functionA, so objectB.data can and should (where possible) be mocked/stubbed in order to get a true unit test. Integration test is another story (you should use the real implementation for that, but your question was specific to unit testing)
Related
Suppose we have a class like this :-
class A {
internal val obj : Obj
get() = Application.getbean(Obj::class)
fun method1(){
val result = obj.somefunc()
..../code/
}
fun method2(){
...../code/
}
}
I wan't to write unit test using the junit mockito framework to test the functionality of method1 and wan't to mock obj object . In some other threads on stackoverflow people has suggested to use constructor dependency injected but that is not possible in my case because of the issue of circular dependency . In some other answers people has suggested to move this object instantiation inside the method ,but i don't want to go that way .Is there any way to mock this obj object.
It's very hard to unit test code, that is written in a non-testable way. That is why you should inject dependencies and not to hold them, that is why you should obtain objects and not to create them by yourself. If you're assume that your code might be tested, always think how first.
In your case it's a bit difficult to mock Obj, but not impossible since the actual creation (constructor calling) of the object is done with a different class (not the one being tested).
In your example you're using static method, maybe you can mock it's behavior with a PowerMockito? Please take a look at this answer.
Other than that, I just can suggest to change the code.
To inject object creating class as a dependency or use some other approaches, which might involve some architectural changes.
I have a testing dilemma:
I'm writing a unit test for Unit A. The method I'm about to test is func(B param). In the (non testing) code the only place where the func(..) is called is in class C, it's also the only place in the project where variables of type B can be instanciated (to be sent as parameters to the func(B param), so the instanciation method is private.
Now, I'm not sure how should I create a B instance inside the Unit test.
Of cause I can change private to public in a method declaration of the method which creates B, but I don't feel right about it, since it'll expose the method to the rest of the project.
I can also simply duplicate the B creation method into the Unit test class, but I hate duplicating code.
Is there some known best practice for such cases?
Thanks a lot,
Dima
You would be looking into using a mocking framework like EasyMock or Mokito to create a "test double" object of your class B here.
As a rule of thumb, only public methods should be tested directly. By extension, public code should test all private code. Depending on what language you're using, you can also force less exposed code to be exposed to unit testing frameworks without having to change every method (e.g. InternalsVisibleTo in C#) but I accept that this option won't be available to all languages using all frameworks.
As well as unit testing, another tool in your armoury should be some sort of code coverage tool to ensure that as much of your code is being covered by said tests as possible.
Just having a conversation with someone in the office about using a business logic class to build up some data in order to test another class.
Basically, he has class A which takes a complex type as a parameter and then generates a collection of a different complex type as a result. He's written tests around this class already. Now he's moved on to testing another class (class B) which takes the result of class A then performs some logic on it.
He's asked the question, "should I use class A to build up a scenario to test class B with".
At first I said yes as class A has tests around it. But then I figured well what if there's some bugs in class A that we haven't found yet... so I guess there must be a better way to address this scenario.
Does anyone have any thoughts on this? Is it OK to use existing logic to save time writing other tests?
Regards,
James
Stances on that might differ. Generally, if code is tested and you assume it works, you're free to use it. This is especially true when using already tested methods to help with testing others (within single class/unit). However, as this happens within single unit it's a bit different from your case.
Now, when dealing with 2 separate classes I'd say you should avoid such approach. Purely for the reason that those two classes might not be related in obvious way or their context/scope of usage might vastly differ. As in, somebody might change class A without even knowing class B exists. Class B tests suddenly break even though no changes were made to B code. This brings unnecessary confusion and is situation you usually don't want to find yourself in.
Instead, I suggest creating helper method within tested class B file. With stubs/fakes and tools like AutoFixture, you should be able to easily reproduce generation logic used by class A and have your own "copy" contained in class B tests.
In order to test class B, the result returned from the class A should be replicated somewhere in your test. If class A returns a list of persons, you will have an helper function in your test returning a fake List<Person> to use for your test.
Because you are only testing the class B, class A should not be used in your test.
NUnit provides a built in functionality in order to provide data for your tests, have a look to :
http://www.nunit.org/index.php?p=testCaseSource&r=2.5
Or you can simply create a DataFactory class with methods that returns the data (simple objects, collections etc..) you will consume in your tests.
I have a constructor and a property in the class:
private IMyCollectionObjects _myCollectionObjects;
public MyClassConstructor(string message)
{
_myCollectionObjects = MyCollection.GetCollectionObejects(message);
}
With as much detail can you please help me understand how to unit test this constructor
and GetCollectionObjects method?
How do I completely decouple the
classes? You can give the answer
using any IoC, I want to
understand the concept.
Thank you.
Dependencies on static members such as GetCollectionObjects are difficult to test because you can't replace its implementation at runtime. This means that you cannot fully isolate an instance of MyClassConstructor from the implementation details of GetCollectionObjects. Without isolation of the test target, it can't really be considered a unit test.
See here for further discussion of static dependencies.
You can refactor this code to be fully decoupled (and thus fully testable):
private readonly IMyCollectionObjects _myCollectionObjects;
public MyClassConstructor(IMyCollectionObjects myCollectionObjects)
{
_myCollectionObjects = myCollectionObjects;
}
This bubbles the knowledge of how to turn a message into a collection right out of MyClassConstructor, making the class simpler, more cohesive, and less coupled.
For of all, unit testing is all about unitary testing, that is, one thing at a time.
With as much detail can you please help me understand how to unit test this constructor and GetCollectionObjects method?
First things first, have you unit tested your MyCollection class?
If not, you should begin with it, as your MyClassConstructor class depends on it, that is the basis of dependency injection. Otherwise, how can you manage to know if the results you're getting are right or wrong? You won't be able to test and be sure that it works flawlessly.
How do I completely decouple the classes? You can give the answer using any IoC, I want to understand the concept.
I my humble point of view, you must have a clear reason to make an object dependant of another using dependency injection. Once you make an object depend on another, it makes no sense, in my opinion, to decouple them. One way of decoupling might be to use Unity Application Block of Enterprise Library.
Unit test this constructor
You generally only need to check for three things while testing such a constructor.
That the constructor doesn't return a null value;
That the instance it returns is of the expected type;
That the object you expect to be instantiated through its dependency is actually instiated.
[TestCase("message")]
public void DependentConstructorTest(string message) {
MyClassConstructor myclass = new MyClassConstructor(message);
Assert.IsNotNull(myclass);
Assert.IsInstanceOf(typeof(MyClassConstructor), myclass);
Assert.IsNotNull(myclass.MyCollection); // Where MyCollection represents the property that
// exposes the instance created of the object from
// which your MyClassConstructor class depends on.
}
Note: This test is written using NUnit attributes and assertion methods. Use whatever else you like.
Here is roughly what you would need to do (with some assumptions).
Assuming MyCollection is a static class and GetCollectionObjects parses a string and returns an IMyCollectionObjects, you would first need to make MyCollection non-static, and pass it through the constructor as well. Static classes/methods used in a class create a tight coupling, more or less by definition.
Now you would be constructing the class passing a message string and a MyCollection. Your constructor uses the two in combination to populate a member variable of type IMyCollectionObjects. In order to ensure that this happens as expected, you will need a way to examine the result from outside the class (i.e. a public method). So you will need a property getter that exposes _myCollectionObjects.
Now you just need to call this contructor from one or more tests, and check the property after construction to ensure parsing the string into a collection was successful.
Note that this is really more of an integration test than a discrete unit test. You are really testing that the parsing was successful. If the class represented here is really what you intend to test, the test would really just be checking that GetCollectionObjects was called. The result of that call is really irrelevant, because you would (presumably) have a separate test or set of tests that ensure that the method GetCollectionObjects on MyCollection works as expected.
I have a basic understanding of mock and fake objects, but I'm not sure I have a feeling about when/where to use mocking - especially as it would apply to this scenario here.
Mock objects are useful when you want to test interactions between a class under test and a particular interface.
For example, we want to test that method sendInvitations(MailServer mailServer) calls MailServer.createMessage() exactly once, and also calls MailServer.sendMessage(m) exactly once, and no other methods are called on the MailServer interface. This is when we can use mock objects.
With mock objects, instead of passing a real MailServerImpl, or a test TestMailServer, we can pass a mock implementation of the MailServer interface. Before we pass a mock MailServer, we "train" it, so that it knows what method calls to expect and what return values to return. At the end, the mock object asserts, that all expected methods were called as expected.
This sounds good in theory, but there are also some downsides.
Mock shortcomings
If you have a mock framework in place, you are tempted to use mock object every time you need to pass an interface to the class under the test. This way you end up testing interactions even when it is not necessary. Unfortunately, unwanted (accidental) testing of interactions is bad, because then you're testing that a particular requirement is implemented in a particular way, instead of that the implementation produced the required result.
Here's an example in pseudocode. Let's suppose we've created a MySorter class and we want to test it:
// the correct way of testing
testSort() {
testList = [1, 7, 3, 8, 2]
MySorter.sort(testList)
assert testList equals [1, 2, 3, 7, 8]
}
// incorrect, testing implementation
testSort() {
testList = [1, 7, 3, 8, 2]
MySorter.sort(testList)
assert that compare(1, 2) was called once
assert that compare(1, 3) was not called
assert that compare(2, 3) was called once
....
}
(In this example we assume that it's not a particular sorting algorithm, such as quick sort, that we want to test; in that case, the latter test would actually be valid.)
In such an extreme example it's obvious why the latter example is wrong. When we change the implementation of MySorter, the first test does a great job of making sure we still sort correctly, which is the whole point of tests - they allow us to change the code safely. On the other hand, the latter test always breaks and it is actively harmful; it hinders refactoring.
Mocks as stubs
Mock frameworks often allow also less strict usage, where we don't have to specify exactly how many times methods should be called and what parameters are expected; they allow creating mock objects that are used as stubs.
Let's suppose we have a method sendInvitations(PdfFormatter pdfFormatter, MailServer mailServer) that we want to test. The PdfFormatter object can be used to create the invitation. Here's the test:
testInvitations() {
// train as stub
pdfFormatter = create mock of PdfFormatter
let pdfFormatter.getCanvasWidth() returns 100
let pdfFormatter.getCanvasHeight() returns 300
let pdfFormatter.addText(x, y, text) returns true
let pdfFormatter.drawLine(line) does nothing
// train as mock
mailServer = create mock of MailServer
expect mailServer.sendMail() called exactly once
// do the test
sendInvitations(pdfFormatter, mailServer)
assert that all pdfFormatter expectations are met
assert that all mailServer expectations are met
}
In this example, we don't really care about the PdfFormatter object so we just train it to quietly accept any call and return some sensible canned return values for all methods that sendInvitation() happens to call at this point. How did we come up with exactly this list of methods to train? We simply ran the test and kept adding the methods until the test passed. Notice, that we trained the stub to respond to a method without having a clue why it needs to call it, we simply added everything that the test complained about. We are happy, the test passes.
But what happens later, when we change sendInvitations(), or some other class that sendInvitations() uses, to create more fancy pdfs? Our test suddenly fails because now more methods of PdfFormatter are called and we didn't train our stub to expect them. And usually it's not only one test that fails in situations like this, it's any test that happens to use, directly or indirectly, the sendInvitations() method. We have to fix all those tests by adding more trainings. Also notice, that we can't remove methods no longer needed, because we don't know which of them are not needed. Again, it hinders refactoring.
Also, the readability of test suffered terribly, there's lots of code there that we didn't write because of we wanted to, but because we had to; it's not us who want that code there. Tests that use mock objects look very complex and are often difficult to read. The tests should help the reader understand, how the class under the test should be used, thus they should be simple and straightforward. If they are not readable, nobody is going to maintain them; in fact, it's easier to delete them than to maintain them.
How to fix that? Easily:
Try using real classes instead of mocks whenever possible. Use the real PdfFormatterImpl. If it's not possible, change the real classes to make it possible. Not being able to use a class in tests usually points to some problems with the class. Fixing the problems is a win-win situation - you fixed the class and you have a simpler test. On the other hand, not fixing it and using mocks is a no-win situation - you didn't fix the real class and you have more complex, less readable tests that hinder further refactorings.
Try creating a simple test implementation of the interface instead of mocking it in each test, and use this test class in all your tests. Create TestPdfFormatter that does nothing. That way you can change it once for all tests and your tests are not cluttered with lengthy setups where you train your stubs.
All in all, mock objects have their use, but when not used carefully, they often encourage bad practices, testing implementation details, hinder refactoring and produce difficult to read and difficult to maintain tests.
For some more details on shortcomings of mocks see also Mock Objects: Shortcomings and Use Cases.
A unit test should test a single codepath through a single method. When the execution of a method passes outside of that method, into another object, and back again, you have a dependency.
When you test that code path with the actual dependency, you are not unit testing; you are integration testing. While that's good and necessary, it isn't unit testing.
If your dependency is buggy, your test may be affected in such a way to return a false positive. For instance, you may pass the dependency an unexpected null, and the dependency may not throw on null as it is documented to do. Your test does not encounter a null argument exception as it should have, and the test passes.
Also, you may find its hard, if not impossible, to reliably get the dependent object to return exactly what you want during a test. That also includes throwing expected exceptions within tests.
A mock replaces that dependency. You set expectations on calls to the dependent object, set the exact return values it should give you to perform the test you want, and/or what exceptions to throw so that you can test your exception handling code. In this way you can test the unit in question easily.
TL;DR: Mock every dependency your unit test touches.
Rule of thumb:
If the function you are testing needs a complicated object as a parameter, and it would be a pain to simply instantiate this object (if, for example it tries to establish a TCP connection), use a mock.
You should mock an object when you have a dependency in a unit of code you are trying to test that needs to be "just so".
For example, when you are trying to test some logic in your unit of code but you need to get something from another object and what is returned from this dependency might affect what you are trying to test - mock that object.
A great podcast on the topic can be found here