Reducing complexity of a method - java

I have a method that does several tasks. It is part of the business logic of the application, but it is poorly readable because of the many if-then and try-catch blocks and the many log calls.
public class MyClass {
boolean createReport, sendReport, warnIfErrors;
public void archiveAll() {
if (createReport) {
//... ...
}
if (sendReport) {
//... ...
}
if (warnIfErrors) {
//... ...
}
}
The idea is to move the tasks into ad hoc methods and have an "archiveAll" method that may be understood at a glance:
public void archiveAll() {
doCreateReport();
doSendReport();
doWarnIfErrors();
}
But as doing this, two problems arise:
if all methods use a local variable, I'll move it as a class field, but this is not good design
I want to move the test if (createReport) into the method doCreateReport too, because part of the complexity derives from the tests that are done. This makes the sub methods poorly cohesive though.

If you have a lot of local variables that are shared between them it might make sense to make a private class to store them together, perhaps even do something like:
MyReport report = new MyReport(); // or MyReport.doCreateReport(); if it makes more sense
report.send();
report.warnIfErrors();
Again, it really depends on whether the function is currently big enough to warrant something like this.
If you can get away with just passing those common variables as parameters without having huge lists of parameters, do that.

You can also pass the required data as arguments to the methods.
I would do the check before calling a method. If a method is called doCreateReport it should actually do that.

Instead of making variables class fields, just parameterize the function and pass the values around. This has another big advantage that your code will now become more unit-testable. I always promote to have each method to be as independent as possible as it helps in UT.
If you had the name changed to checkAndCreateReport then, will you still think that way:)

Related

If I have multiple JUnit test classes, but they share a large amount of setup, is there a way to resuse some of this setup code?

I have a number of classes I'm testing, and I've seperated all of the tests for these classes out into their own files. i.e. I have the following sort of directory structure
src
ClassOne.java
ClassTwo.java
test
ClassOneTests.java
ClassTwoTests.java
I have a much larger number of classes to test than this however. I've started to write tests for many of these classes, and I realised that there is a lot of code in the setup that is the same between them all. I'd like to be able to reuse this code, both to reduce the time it takes to write more tests, but also in the event that I end up making modifications to my code base, I want to only have one point in the tests to change, rather than many dozens of almost identical instatiation of mocks.
An example of my code layout is like this:
public class ClassOneTests {
//Declare global variables that are dependencies for the test
AClass var1;
// etc...
ClassOne testThis;
#Before
public void setUp() throws Exception {
//instantiate and populate the dependencies
var1 = new AClass();
// etc...
testThis.setDependencies(var1, //And other dependencies....);
}
#Test
public void aTest() {
//Do test stuff
Var result = testThis.doStuff();
Assert.NotNull(result);
}
// etc...
}
This means a huge majority of stuff in my declaration and setUp method is duplicated across my class tests.
I have partially solved this by simply having a GenericTestSetup.java that does all of this setup and then each ClassXTest.java extends it. The problem lies with the few classes that are unique to each ClassXText.java file, but used in each method. So, in the example above AClass is a variable specific for ClassOneTests. When I do ClassTwoTests I'd have a bunch of shared variables, but then instead of AClass I'd have BClass, for example.
The problem I'm having is that I can't declare two #Before tags, one in the GenericTestClass for the generic setup, and then another in the ClassXTest class if any of the objects inside ClassXTest are dependant on something in GenericTestClass because you can't guarantee an execution order.
In summary, is there a way to have this generic test setup that's used for multiple class tests, but also have another setup method for each specific class that is guaranteed to run after the generic objects have been set up?
EDIT: It was suggested that my question is a duplicate of this question: Where to put common setUp-code for differen testclasses?
I think they're similar, but that question was asking for a more general approach in terms of policy, I have a more specific set of requirements and asking for how it would actually be implemented. Plus, none of the answers there actually gave a proper answer about implementation, which I require, so they're not useful to me.
What i usually do when overloading increases the complexity, I use, what i call Logic classes...
Basically class with static methods which takes the parameters that need to be initialized, and sets them up.
Logic.init(param1, param2)
and I usually use only one #Before with different logic methods.
Advantage is that the code might be shared between similar initializations, and you can reuse the code in the Logic class itself. Example
Logic.init(param1,param2,param3) can call Logic.init(param1,param2), and you can use different variants into the different #Before methods.
EDIT:
I do not know if there is pattern, or a name related to such solution. If there is i would like to know the name as well :).
You could use Template Method pattern. The #before method in the generic class calls a protected method in the same class which is empty but can be overriden in the implementing classes to add specific behaviour.

Correct design for certain methods

Consider you have a class RunMe. As the name supposes it is ran by another class. Let's asume through RunMe.run().
RunMe has a private variable with Data that it uses to run different Tests, lets call ist data.
Let's say this data is initialized by RunMe.initialize().
After that, in the run() Method, the first Test is ran with the default values set by the initialize function for data. Let's call that test-method testWithDefaultValues.
We now want to fill our data with some custom data. Let's say we do this using fillData.
Then we want to execute another test using our newly filled data. Let's call this test testWithFilledData.
Our run-method at this point would look something like this
public void run() {
initialize();
testWithDefaultValues();
fillData();
testWithFilledData();
}
Can you see how akward this code looks? It looks AND feels wrong. A thing directly coming into my mind: The only reason testWithFilledData() or also testWithDefaultValues()is actually doing what the name supposes is because of the order in which these functions are called in run. This has to be wrong.
So instead i should eliminate initialize and fillData and do what those functions do in the according test-function?
What if you consider the fact that many more test-functions are going to exist, each of them testing with a different set of data, all of which have to be quite manually filled (data.setField("fooField","fooValue);).
Can someone possibly give a general construct or idea in which he would explain how he would solve the given task properly?
Right now i am really struggeling to find a pattern that "feels nice" and correct. What i am doing currently must be wrong.
Edit: Worth mentioning is that the test-function cannot be generic. For every different variations of data different results have to be considered.
Well, what would happen if you attempt to call testWithDefaultValues() without calling initialize() first? You won't actually be testing with the default values, you will be testing with whatever you previously set data to. I think you should move away from modifying the internal test data in the actual test functions, and perhaps rather have a generic test function that has data passed into it.
This makes a lot of sense if testWithDefaultValues() and testWithFilledData() are actually doing the same thing but with different data.
I think something like this makes more sense:
Data testData = getTestData();
test(testData);
Data fillData = getFillData();
test(fillData);
I believe you should fill only one method with all the code needed for the test you are trying to achieve. You are then able to fill the variables or data for your test accordingly and stage different values for your data to run different test starting always from the same method.
With this simple construct, you are able to create multiple tests method and won't get lost in your code.
EDIT
You should always consider a test method like a blackbox testing. If you consider that you have no idea what's the code running inside the method. All you have to care about is the input and output of you test.
If the same method should produce different output based on different input. The code inside your blackbox remains the same.
However, if your method needs to interact differently with the input to generate the output you need, then, you need to consider writing a different test.
My two cents, hope it helps
I suggest using the Template Method design pattern to create a test framework. You'd probably be better off using a mature test framework like JUnit.
public abstract class TestCase {
// This is the template method.
public final boolean execute() {
initTest();
return runTest();
}
// Init hook method.
public abstract void initTest();
// Test logic hook method.
public abstract boolean runTest();
}
public abstract class BaseTest extends TestCase {
public boolean runTest() {
// This is the common execution for different data sets...
}
}
public Test1 extends BaseTest {
public void initTest() {
// Data init for test 1...
}
}
You can extend BaseTest for each test data set you have. To run the tests:
new Test1().execute();
new Test2().execute();
EDIT: You can of course skip BaseTest if you don't have common test logic. Or you can tailor the template method to add more hooks for whatever makes sense for your particular needs. The main point is to capture the common process in the template method, to isolate common code in some hook methods, and to provide unique concrete overrides in other hook methods.

OOP Design, Calling Certain Methods Outside of a Main Class

In my class, we are to create a project with several Main classes and shared classes. In one specific main class, called UserApp, I create an object of the class UserInterface, which deals directly with a file, called Log.txt.
I create an object of the class,DataStorage inside of UserApp, which I use to call a method that returns a String value back to UserApp. I then take that string value and pass it to a method in UserInterface which will write to the file Log.txt. For Example:
public class UserApp {
public static void main(String[] args) {
UserInterface ui = new UserInterface();
String[] commands = ui.readCommandLine();
while(!ui.isFileEnd()){
switch(command[0]){
case "LI": ui.displayThis(dataStorage.listById());
break;
case "QI": ui.displayThis(dataStorage.queryById(command[0]));
}
}
}
}
public class DataStorage {
public String queryById(String id) {
// Stuff the method does goes here
return stringToReturn;
}
}
To me, this seems like the most OOP way of doing things. I emailed her and asked her if this was the correct use. She said to call ui.displayThis inside of the listById() in DataStorage... that would mean that I need to either create a UserInterface object inside the DataStorage class, or pass the DataStorage object in as a parameter to listById(). If I did it like she said, the method listById() wouldn't return a string, but would be void. For Example:
public class UserApp {
public static void main(String[] args) {
String[] commands = ui.readCommandLine();
while(!ui.isFileEnd()){
switch(command[0]){
case "LI": dataStorage.listById(); // Here is the difference
break;
case "QI": dataStorage.queryById(command[0]); // And here
}
}
}
}
public class DataStorage {
public void queryById(String id) {
UserInterface ui = new UserInterface();
// Stuff the method does goes here
ui.displayThis(stringToDisplay);
}
}
There are more switch statements and methods but I felt they were unnecessary to show for this question. I've done some research on this, and from what I've gathered, I'm not sure that this is a style preference or if one way is better than the other. the way she wants me to do it just doesn't feel right with an OOP language. Which method would actually be correct for OOP design?
Edit: The second part would actually be passing in a UserInterface object as a parameter. This seems to make more sense then creating the object each time. Would this be a better way to do it?
The first thing you should know is that both ways of doing it would "work", meaning that you'd accomplish what you set out to do, which is to retrieve something from data storage and display it in the UI.
However, getting something to just "work" isn't always best. In real world applications, engineers such as myself are concerned with maintainability. Simply put, maintainability means that at some point in the future, I may have to come back in to this piece of code and add functionality, or change the way something works (vs. something like a school project where you write the code, submit it, and then never see it or use it again). If I've got a well-written component that has dependencies on other components only where they're necessary, then I can modify and test the said component easily and be confident that I'm not changing the behavior of other components.
So back to your question - the first method that you proposed has a DataStorage class with one method, queryById, that takes a parameter and returns a value. It doesn't have any dependencies on a display component. This is the correct method of structuring your code in my opinion. The fewer dependencies, the better -- it's easier to maintain, and it's easier to write tests for. If you don't believe me, try to write a unit test using JUnit or another testing framework for both ways of implementing the queryById method -- you'll find that your method is simpler to test because you don't have to mock out or inject or create an instance of the UI component.
With the information you've given, it seems that the first way is designed to be more flexible. Rarely do professionals write systems where the storage layer talks directly to the UI layer.
Your first example seems to follow the MVC pattern. The second example seems to be more like the GoF Command pattern.
Either will work, it's just a question of maintainability.
However, OO design is all about separating concerns of the overall program into smaller cohesive units.
What I don't like about your teacher's solution
Querying something from a data store and writing to a file (which is apparently the applications user interface) are two separate things, and your queryById method shouldn't do both. The fact that you create a UserInterface object in that method makes it even worse, but that could be solved by passing it in the constructor and storing it in a (final) field.
The reason your teacher is suggesting this, is probably because she favors the Tell, Don't Ask principle. See Martin Fowler's Bliki for a good explanation of this principle: http://martinfowler.com/bliki/TellDontAsk.html He also explains why he doesn't use it. As you correctly observed: your queryById method wouldn't return a value. Actually then by definition it wouldn't be a query method anymore, but query methods aren't always bad.
What I suggest
Your DataStore class represents the model, your UserInterface class represents the view. Start from your first solution, add another class to represent the controller, which calls the DataStore and UserInterface, both of which are passed in the constructor by your main method, which is otherwise empty. Due to the fact that the logic is now in the controller instead of the main method, it is testable (probably needing Test Doubles for both the DataStore and the UserInterface).
If it were me, I'd be fine with having listById be a void function that does the displaying (instead of returning a String) ... but I'd do it something like this:
public interface DisplayMethod {
public void display (String s);
}
public class DataStorage {
public void queryById(String id, DisplayMethod displayer) {
// UserInterface ui = new UserInterface(); DELETE THIS LINE
// Stuff the method does goes here
displayer.display(stringToDisplay);
}
}
and in UserApp:
final UserInterface ui = new UserInterface();
...
DisplayMethod displayer = new DisplayMethod () {
public void display (String s)
{ ui.displayThis (s); }
};
...
case "QI": dataStorage.queryById(command[0], displayer);
Or something similar. (You'd have to add final to the declaration of ui.) The effect here is that you can still make queryById be a void function (which is useful if it's going to display more than one string), but you don't hard-wire the information about how to do the displaying into DataStorage, since it really doesn't belong there. Your instinct that the stuff to deal with the UserInterface should be in one place, rather than spread out over several classes, is a very good one. Congratulations. (P.S. I'm not claiming that DisplayMethod is a good name. Naming things is one of my weak points.)

Unit test for method that calls multiple other methods using Mockito

Perhaps I have completely fallen short in my search, but I cannot locate any documentation or discussions related to how to write a unit test for a Java class/method that in turn calls other non-private methods. Seemingly, Mockito takes the position that there is perhaps something wrong with the design (not truly OO) if a spy has to be used in order to test a method where mocking internal method calls is necessary. I'm not certain this is always true. But using a spy seems to be the only way to accomplish this. For example, why could you not have a "wrapper" style method that in turn relies on other methods for primitive functionality but additionally provides functionality, error handling, logging, or different branches dependent on results of the other methods, etc.?
So my question is two-fold:
Is it poorly designed and implemented code to have a method that internally calls other methods?
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
This might be a difficult request, but I would prefer for those who decide to answer to not merely re-publish the Mockito verbiage and/or stance on spies as I already am aware of that approach and ideology. Also, I've used Powermockito as well. To me, the issue here is that Mockito developed this framework where additional workarounds had to be created to support this need. So I suppose the question I am wanting an answer to is if spies are "bad", and Powermockito were not available, how is one supposed to unit test a method that calls other non-private methods?
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really. But I'd say that, in this situation, the method that calls the others should be tested as if the others where not already tested separately.
That is, it protects you from situations where your public methods stops calling the other ones without you noticing it.
Yes, it makes for (sometimes) a lot of test code. I believe that this is the point: the pain in writing the tests is a good clue that you might want to consider extracting those sub-methods into a separate class.
If I can live with those tests, then I consider that the sub-methods are not to be extracted yet.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
I'd do something like that:
public class Blah {
public int publicMethod() {
return innerMethod();
}
int innerMethod() {
return 0;
}
}
public class BlahTest {
#Test
public void blah() throws Exception {
Blah spy = spy(new Blah());
doReturn(1).when(spy).innerMethod();
assertThat(spy.publicMethod()).isEqualTo(1);
}
}
To me, this question relates strongly to the concept of cohesion.
My answer would be:
It is ok to have methods (public) that call other methods (private) in a class, in fact very often that is what I think of as good code. There is a caveat to this however in that your class should still be strongly cohesive. To me that means the 'state' of your class should be well defined, and the methods (think behaviours) of your class should be involved in changing your classes state in predictable ways.
Is this the case with what you are trying to test? If not, you may be looking at one class when you should be looking at two (or more).
What are the state variables of the class you're trying to test?
You might find that after considering the answers to these types of questions, your code becomes much easier to test in the way you think it should be.
If you really need (or want) to avoid calling the lower-level methods again, you can stub them out instead of mocking them. For example, if method A calls B and C, you can do this:
MyClass classUnderTest = new MyClass() {
#Override
public boolean B() {return true;}
#Override
public int C() {return 0;}
};
doOtherCommonSetUp(classUnderTest);
String result = classUnderTest.A("whatever");
assertEquals("whatIWant", result);
I've used this quite a quite a bit with legacy code where extensive refactoring could easily lead to the software version of shipwright's disease: Isolate something difficult to test into a small method, and then stub that out.
But if the methods being called are fairly innocuous and don't requiring mocking, I just let them be called again without worrying that I am covering every path within them.
The real question should be:
What do I really want to test?
And actually the answer should be:
The behaviour of my object in response to outside changes
That is, depending on the way one can interact with your object, you want to test every possible single scenario in a single test. This way, you can make sure that your class reacts according to your expectations depending on the scenario you're providing your test with.
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really, and really not! These so called private methods that are called from public members are namely helper methods. It is totally correct to have helper methods!
Helper methods are there to help break some more complex behaviours into smaller pieces of reusable code from within the class itself. Only it knows how it should behave and return the state accordingly through the public members of your class.
It is unrare to see a class with helper methods and normally they are necessary to adopt an internal behaviour for which the class shouldn't react from the outside world.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
In my humble opinion, you don't test those methods. They get tested when the public members are tested through the state that you expect out of your object upon a public member call. For example, using the MVP pattern, if you want to test user authentication, you shall not test every private methods, since private methods might as well call other public methods from an object on which depend the object under test and so forth. Instead, testing your view:
#TestFixture
public class TestView {
#Test
public void test() {
// arrange
string expected = "Invalid login or password";
string login = "SomeLogin";
string password = "SomePassword";
// act
viewUnderTest.Connect(login, password);
string actual = viewUnderTest.getErrorMessage;
// assert
assertEqual(expected, actual);
}
}
This test method describes the expected behaviour of your view once the, let's say, connectButton is clicked. If the ErrorMessage property doesn't contain the expected value, this means that either your view or presenter doesn't behave as expected. You might check whether the presenter subscribed to your view's Connect event, or if your presenter sets the right error message, etc.
The fact is that you never need to test whatever is going on in your private methods, as you shall adjust and bring corrections on debug, which in turn causes you to test the behaviour of your internal methods simultaneously, but no special test method should be written expressly for those helper method.

How to unit test a private functionality

I have a question regarding unit testing.
I have a function which does the following thing:
void myFunction(List<MyClass> myList) {
// 1. Sort the list
// 2. Post Process the list
}
Now I want to test this function. But the problem is I should not test these two things at the same time. I am therefore thinking to extract the "Post Process the list" part as a separate function.
But the problem is the task of "Post Process the list" is only used by myFunction and I want to make it private to the class.
If I make it private I won't be able to test it from outside.
What is the general rule of this kind of scenario? Must I change a private function to public only for testing?
Or if there are any other patterns I should use?
Many thanks
The test method only needs to be package-local.
You can call private methods using reflections and there are mocking libraries which allow you to test private methods. But I would just make it package-local as it shows the method is access from elsewhere in the package (which it is either way)
As others have said, you don't need to make the method public, just package visible.
Google Guava has a #VisibleForTesting annotation which is meant for situations like this. You put this annotation on a method, just to document that the reason that the method isn't private is only for testing. The annotation doesn't do anything, it's just meant as a warning for programmers that they shouldn't call it from outside the class. (Some static code checking tool could in principle check if methods with this annotation aren't called from anywhere except inside the class or from test code).
Ofcourse it's kind of ugly to have to modify your code to do this just for testing. If you want to avoid this, you can do tricks with reflection to call the private method:
public class Sandbox {
public static void main(String[] args) throws Exception {
Example e = new Example();
Method m = Example.class.getDeclaredMethod("myFunction", List.class);
m.setAccessible(true);
m.invoke(e, Arrays.asList("one", "two", "three"));
}
}
class Example {
private void myFunction(List<String> data) {
System.out.println("Hey, what are you doing! " + data);
}
}
In general, you should always test the functionality through public methods. If there is some functionality in private methods, which cannot otherwise be tested well enough, that's an indication that the method has a responsibility which should be moved to its own class (this also helps to achieve high cohesion). Then that newly extracted class can be tested directly though its public methods.
Another vote for package-local. Just ensure that your newly exposed method is clearly named and documented so that in future it is not called inappropriately.
It depends.
Dose the sub routine contains common behavior that you should extract ?
Take your first sub routine as example. If you're not sorting your list by Comparator<T>, you should refactor it, then test that Comprartor<T> class instead of your private method. If Post process are actually some algorithm or common business logic, you might want to refactor it using Strategy pattern then test those class you just extract.
The point is, if a private method is complex enough to require a unit-test, then chance is probably you should not put them there, otherwise you should just test through it's public API.
It's a legacy system, and it will take forever to refactor that method.
check Bad Smells in Code : Long method for long method refactor, Method Object is a good strategy for things like this.
It's fine, I just want to test them.
Then you can test through Java reflection API, and I believe there are some mocking framework like PowerMock can also help you.
Below things you may consider for testing a private method.
1.create public method written only for the purpose of testing. (or)
2.create nested class for testing (or)
3.use reflection to test it.
useful link,another useful link from stackoverflow
I typically consider private methods to be part of the method under test. They typically consist of code that has been moved out of the original method to make it leaner and shorter, and more modular. However from a test perspective you would be testing the same code if you moved the content of the private method into your method under test.
The question of trying to isolate the return values of private methods to simulate various conditions is is often valid though. I think its' part of the larger question of how to write testable code.
One approach with very little overhead is to rely on basic overriding of methods. You can make your private methods protected virtual instead, and override them in your test:
Here's an example of that too :
http://www.unit-testing.net/CurrentArticle/How-To-Remove-Data-Dependencies-In-Unit-Tests.html
The example is C#, but the concept applies to all object oriented languages

Categories

Resources