I'm trying to use TDD when writing a class that needs to parse an XML document. Let's say the class is called XMLParser, and its constructor takes in a string for the path to the XML file to parse. I would like to have a Load() method that tries to load this XML into memory, and performs a few checks on the file such as file system errors, whether or not its an XML file, etc.
My question is about alternatives: I've read that it's bad practice to have private methods that you need to test, and that you should be able to just test the public interface and let the private methods do their thing. But in this case, this functionality is pretty important, and I don't think it should be public.
Does anyone have good advice for a scenario like this?
I suggest to redesign your architecture a bit. Currently, you have one high level class with low level functionality embedded. Split that into multiple classes that belong to different layers (I use the term "layer" very loosely here).
Example:
Have one class with the public interface of your current class. (-> High level layer)
Have one class responsible for loading files from disk and handling IO errors (-> Low level layer)
Have one class responsible for validating XML documents (-> Inbetween)
Now you can test all three of these classes independently!
You will see that your high level class will do not much more than just composing the two lower level classes.
Use no access modifier (which is the next up to private) and write the test in the same package.
Good OOD is important but for really important functionality testing is more important. Good practices are always only a guideline and they are good in the general scenario.
You could also try to encapsulate that specific file-checking behaviour in another object and have your parser instantiate it and use it. This is probably what I would do. In this way you could also even use this functionality somewhere else with minimal effort.
You can make a subclass as part of your test package that exposes public accessors to the private methods (which should then be protected).
Public class TestableClass : MyClass
{
public someReturnType TestMethod() {
return base.PrivateMethod();
}
}
Related
So I am learning TDD using the many resources here on SO, but I just cant seem to figure out what I do with private/protected objects instantiated inside a given method/constructor. Lets say I have a connection string. That connection string is used to construct a Sqlcommand or Sqlhelper. Well I want to mock that Sqlhelper so that when I test other methods I don't have to rely on the results coming from my database. But I cant access the Sqlhelper.
How do I work around this?
Its generally best (except for a very few rare occasions) to test only the public interface of the class as a whole. Try not to use one of the workaround methods (such as private objects) unless you really have to. Accessing private members of classes in tests tends to look good at first as theres less code to write to test an object, however when things start to change (and they will) anything accessing the internals of a class makes it more difficult to change its implementation, this can be crippling to a project if most of the tests are written in this way.
In this particular case you are interacting with an external dependency outside of your control (i.e. SqlHelper), I'd recommend wrapping the SqlHelper object in your own object that implements an ISqlHelper interface (or a more reasonably named interface for your scenario).
e.g.
public interface ISqlHelperWrapper
{
void ExecuteQuery();
}
Then inject this in through the constructor of you're object under test:
public class SqlConsumer
{
private ISqlHelperWrapper _sqlHelper;
public SqlConsumer(ISqlHelperWrapper helper)
{
this._sqlHelper = helper;
}
public void QuerySomething()
{
this._sqlHelper.ExecuteQuery();
}
}
Not only is this a better design (you've isolated the sql implementation specific stuff from the SqlConsumer, and given it fewer reasons to change). But you can now mock the ISqlHelper instance using a mocking framework as well as switch the implementation on construction.
Given your connectionstring scenario above, you could initialise the sqlhelperwrapper (There are better names for this) with the connectionstring and your SqlConsumer object doesn't need to know about it.
At my workplace there seems to currently be a crusade against static classes. I can understand part of that, they do sort of break the whole unit testing modularity thing. However, I am seeing an influx of code reviews that call for removing static classes.
A common case is a utility class this is spring-injected with a few other objects that are "known" at compile-time. It has no other member variables. If class M is calling this static class, I always see the suggestion to make this utility class non-static and inject it into class M.
This doesn't make sense to me. I don't particularly see anything wrong with it other than that it seems a waste of time and makes utility class less easily usable. As far as I can tell the justification is usually for unit testing, but I don't like the idea that valid code has to be changed to conform to a testing paradigm. Admittedly mocking a simple static utility class would probably be overkill.
Are static classes appropriate in this use case, or best avoided?
I think the differences in the two approaches are small, but as long as the class contain no state it is slightly better to make it static. Let's say I have this code in class A:
StaticClass.utilMethod()
If I want to use this code in class B I can copy and paste. That's it. No adding member variables, injection, etc. cmd-c cmd-v.
Considering your existing code uses static classes and modifying that will take work, it's definitely best to continue using static classes.
I vote for using the static classes... i.e. A class with just static methods for purely Utility purposes. Even java has provided us such classes like java.util.Collections and java.util.Arrays
If you pretend for a moment that your static class did not belong to you, that it was, say, part of the .NET framework, how would your team handle it? Their answer would be my answer. In other words, if their answer to that question is inconsistent with what they're asking you to do, then they should probably either change how they work with .NET static classes or with how they work with yours.
I avoid using static classes (assuming we are actually talking about classes that contain static methods), and I do it for the sake of testability.
If you are using static methods, you will have a difficult time mocking/stubbing the portion of your code that uses said static for your unit tests.
Consider this:
public String myMethod() {
String complicatedStringOutput = MyUtility.createComplicatedStringOutput();
//do some more complicated work on this String
}
To write a unit test for this method, how would you go about making it a 'true unit test' without needing to also test the creation of complicatedStringOutput? In my unit tests, I prefer to test only the method that is the focus of the unit test.
Change it to this:
public String myMethod(MyNonStaticUtility util) {
String complicatedStringOutput = util.createComplicatedStringOutput();
//do some more complicated work on this String
}
Suddenly, this class is much easier to write a 'true unit test' for. You can control the behavior of MyNonStaticUtility by either using a stub or mock.
All that said, it is really up to you (or your Business Unit). If you value unit tests and feel that it is important to have good test coverage of your complicated code, this is the preferred approach. If you do not have time/money to invest in 'fixing' your code, then it just won't happen.
Depends, naturally.
How do you want to test the code that uses the static classes?
Do the static classes encapsulate behavior you'll need to mock often?
Will anybody ever need to modify the behavior of those static classes?
Finally:
Is there a compelling reason not to inject a Spring-managed singleton bean?
Admittedly mocking a simple static utility class would probably be overkill.
You're absolutely right on this. Static classes should only be used for utility classes that are extremely simple, where there is no benefit of mocking such a class. If you're using them for any other purpose, you should rethink your design.
Is it reasonable to use a non-static class if that class does not contain state?
This really has nothing to do with state. For example, strategy objects often contain no state, yet they are not static; they usually implement a common interface and need to be interchangeable / mockable.
Could somebody explain is it possible to have potected, pivate methods in playfamewok's contolles except:
public static void method-action-name() {}
For example if I would have method like this:
protected static int doSomeWork() {}
and this method would be invoked in method-action-name() ..
public static void method-action-name() {
...
int resul = doSomeWork();
...
}
I do not want to have long action-method, so I would like to split it to smaller ones, and then reuse it in other action-methods.
I mean is it ok (from playframework's point of view) to have such method in controller side instead of having them in domain classes? In Spring Framework, we use BP (business process) beans for that, for example.
Is it ok to have such helper methods for business methods in playframework controllers ?
Added after having answer & comments:
For example if I have SearchController class then for that class would be nice to have methods like preSearch1(), preSearch2() what search() method would use, but if I move these methods (1,2) to another class then it should be class with name like SearchHelper then? in package named /src/helpers.. not very nice because they related to search too. But maybe then into /src/bp/SearchBP (bp=business-process). And then in controllers/Search i use /bp/SearchBP that use some Model object with .save() DAO methods (SearchBP can use Domain methods and Search class can use Domain methods as well)
The question here: what class ant package would be nice for those methods? (i just did watch it in examples - there alway very simple usage of controllers that use domain object that why i ask)
yes, you can. Controllers are normal classes, you can add whatever you want. It may not be recommended to clutter them with helper methods, I personally would move them to another class, but you can do what you say.
ANSWER TO EDIT:
The name of the package is "irrelevant", won't change it too much :). You can put them under controllers.support.search which would mean controllers.support is a package with helper classes and the subpackage search contains helper classes and methods related to search.
One alternative (which I like more) is to create a Service layer for that, in a "services" package. You seem to come from a Spring background, so it should come naturally to you. These services are instantiated in the controller as required, or maybe just used via static methods, and do the main business logic. That way the controller only tackles the "higher level" logic.
Another alternative is to move as much of that logic as possible into the Model (avoidid the Anemic Domain Model), and using the Model classes from the controller.
As most decisions in development, which one is better depends on your experience, possible impact/limitations in the codebase, practices in your project... anyway, you can always refactor. Just choose the one that you are more used to (it seems to be Services approach) and code away :)
Any behaviour that's complicated enough to be described as "business logic" (rather than "presentation logic") belongs in the model, not the controller. If your model does nothing but map to/from a set of database tables, then it isn't doing its job properly. Things like permissions and access control, in particular, should be enforced by the model.
A very specific question from a novice to TDD:
I separate my tests and my application into different packages. Thus, most of my application methods have to be public for tests to access them. As I progress, it becomes obvious that some methods could become private, but if I make that change, the tests that access them won't work. Am I missing a step, or doing something wrong, or is this just one downfall of TDD?
This is not a downfall of TDD, but rather an approach to testing that believes you need to test every property and every method. In fact you should not care about private methods when testing because they should only exist to facilitate some public portion of the API.
Never change something from private to public for testing purposes!
You should be trying to verify only publicly visible behavior. The rest are implementation details and you specifically want to avoid testing those. TDD is meant to give you a set of tests that will allow you to easily change the implementation details without breaking the tests (changing behavior).
Let’s say I have a type: MyClass and I want to test the DoStuff method. All I care about is that the DoStuff method does something meaningful and returns the expected results. It may call a hundred private methods to get to that point, but I don't care as the consumer of that method.
You don't specify what language you are using, but certainly in most of them you can put the tests in a way that have more privileged access to the class. In Java, for example, the test can be in the same package, with the actual class file being in a different directory so it is separate from production code.
However, when you are doing real TDD, the tests are driving the class design, so if you have a method that exists just to test some subset of functionality, you are probably (not always) doing something wrong, and you should look at techniques like dependency injection and mocking to better guide your design.
This is where the old saying, "TDD is about design," frequently comes up. A class with too many public methods probably has too many responsibilities - and the fact that you are test-driving it only exposes that; it doesn't cause the problem.
When you find yourself in this situation, the best solution is frequently to find some subset of the public methods that can be extracted into a new class ("sprout class"), then give your original class an instance variable of the sprouted class. The public methods deserve to be public in the new class, but they are now - with respect to the API of the original class - private. And you now have better adherence to SRP, looser coupling, and higher cohesion - better design.
All because TDD exposed features of your class that would otherwise have slid in under the radar. TDD is about design.
At least in Java, it's good practice to have two source trees, one for the code and one for the tests. So you can put your code and your tests in the same package, while they're still in different directories:
src/org/my/xy/X.java
test/org/my/xy/TestX.java
Then you can make your methods package private.
I have a class called FooJob() which runs on a WCF windows service. This class has only 2 public methods, the constructor, and a Run() method.
When clients call my service, a Dim a new instance of the Job class, pass in some parameters to the ctor, then call Run()...
Run() will take the parameters, do some logic, send a (real time) request to an outside data vendor, take the response, do some business logic, then put it in the database...
Is it wise to only write a single unit test then (if even possible) on the Run() function? Or will I wind up killing myself here? In this case then should I drill into the private functions and unit test those of the FooJob() class? But then won't this 'break' the 'only test behavior' / public interface paradigm that some argue for in TDD?
I realize this might be a vague question, but any advice / guidance or points in the right direction would be much appreciated.
Drew
do some logic, send a (real time) request to an outside data vendor, take the response, do some business logic, then put it in the database
The problem here is that you've listed your class as having multiple responsibilities... to be truly unit testable you need to follow the single responsibility principle. You need to pull those responsibilities out into separate interfaces. Then, you can test your implementations of these interfaces individually (as units). If you find that you can't easily test something your class is doing, another class should probably be doing that.
It seems like you'd need at least the following:
An interface for your business logic.
An interface defining the request to the outside vendor.
An interface for your data repository.
Then you can test that business logic, the process of communicating with the outside vendor, and the process of saving to your database separately. You can then mock out those interfaces for testing your Run() method, simply ensuring that the methods are called as you expect.
To do this properly, the class's dependencies (the interfaces defined above) should ideally be passed in to its constructor (i.e. dependency injection), but that's another story.
My advice would be to let your tests help with the design of your code. If you are struggling to execute statements or functions then your class is doing too much. Follow the single-responsibility-priciple, add some interfaces (allowing you to mock out the complicated stuff), maybe even read Fowler's 'Refactoring' or Feather's 'Working With Legacy Code', these taught me more about TDD than any other book to date.
It sounds like your run method is trying to do too much I would separate it up but if you're overall design won't allow it.
I would consider making the internal members protected then inheriting from the class in your test class to test them. Be careful though I have run into gotchas doing this because it doesn't reset the classes state so Setup and TearDown methods are essential.
Simple answer is - it depends. I've written a lot of unit tests that test the behaviour of private methods; I've done this so that I can be happy that I've covered various inputs and scenarios against the methods.
Now, many people think that testing private methods is a bad idea, since it's the public methods that matter. I get this idea, but in my case the public method for these private calls was also just a simple Run() method. The logic of the private methods included reading from config files and performing tasks on the file system, all "behind the scenes".
Had I just created a unit test that called Run() then I would have felt that my tests were incomplete. I used MSTest to create accessors for my class, so that I could call the private methods and create various scenarios (such as what happens when I run out of disk space, etc).
I guess it's each to their own with this private method testing do/or don't do argument. My advice is that, if you feel that your tests are incomplete, in other words, require more coverage, then I'd recommend testing the private methods.
Thanks everyone for the comments. I believe you are right - I need to seperate out into more seperate classes. This is one of the first projects im doing using true TDD, in that I did no class design at all and am just writing stub code... I gotta admit, I love writing code like this and the fact I can justify it to my mangagment with years of backed up successful results is purely friggin awesome =).
The only thing I'm iffy about is over-engineering and suffering from class-bloat, when I could have just written unit tests against my private methods... I guess common sense and programmers gut have to be used here... ?