writing testable code in this scenario [duplicate] - java

This question already has answers here:
Writing/implementing an API: testability vs information hiding
(6 answers)
Closed 7 years ago.
I am trying to determine the best way to write testable code. Here's my code
class FileReader {
private FileInputStream input;
public FileReader(FileInputStream input) {
this.input = input;
}
public void read() throws IOException {
Row row = readHeaderRow();
Row[] rows = readOtherRowsBasedOnHeader(row);
doSomethingElse(rows);
}
private void readHeaderRow() {
//..
}
private void readOtherRowsBasedOnHeader(Row row) {
//..
}
private void doSomethingElse(Row[] rows) {
//..
}
}
as you can see from above, only the read() method is public. Rest of the methods are private. Should I just leave private methods out from testing? Or does it make sense to make all methods public and do what read() is doing in the calling code?

My view is that you should only test public methods. The usage of the private methods will be tested regardless by calls from the public method. It will also make internal refactoring much easier without changing the test.
What you want to test is that the class fulfills its contract, ie. the public methods, no matter how it looks on the inside.

If logic of private methods (readHeaderRow, readOtherRowsBasedOnHeader, ...) is complex and require separate tests I suggest to implement FileReader as a composition of smaller classes. It would be something like:
class FileReader {
private FileHeaderReader headerReader = new FileHeaderReader();
private FileOtherReader otherReader = new FileOtherReader();
//....
private FileInputStream input;
public FileReader(FileInputStream input) {
this.input = input;
}
public void read() throws IOException {
Row row = headerReader.read();
Row[] rows = otherReader.read(row);
//do something else
}
}
class FileHeaderReader {
public Row read() {...}
}
//....
Then you can write tests that precisely test logic of each part/class. You can also think about injecting FileHeaderReader into FileReader so this classes are not tightly coupled.

If the testing of the public method covers all the code in the private methods, is safe to consider the class tested

I see two viable options.
You test the read(), so your test should cover the conditions and states changed in the private methods. It really depends on the responsibility and complexity of those methods whether you want to do that.
You find out those private methods violate SRP and separate them so they are now public in a different class.

Related

Refactoring static mocks in Mockito 3.4

I have a Jupiter based UnitTest in a java project where I need to mock some static methods of an external utility. Mockito 3.4 allows for mocking static methods, so no need for PowerMock any more. We all use static mocks by defining them in a try(){} block and overwriting methods on those static mocks inside the block. All fine, but things sometimes get annoying when you have to implement a non trivial mocking cascade. Which is especially annoying of you have to do that in several test cases inside your test class.
class ClassA {
public static void methodA() { ... }
public static void methodB() { ... }
}
class ClassB {
public static void methodA() { ... }
public static void methodB() { ... }
}
class ClassC {
public static void methodA() { ... }
public static void methodB() { ... }
}
class ClassX {
public int doSomething() {
// does something using static methods from classes ClassA, ClassB, ClassC
return 3;
}
}
A test class might (roughly) look like that (please excuse typos and nonsense, this is only meant as a demonstration, this is not working code):
#Test
void test_doSomething() {
int result = 0;
ClassX classX = new ClassX();
try (MockedStatic<ClassA> classAMockStatic = Mockito.mockStatic(ClassA.class);
MockedStatic<ClassB> classBMockStatic = Mockito.mockStatic(ClassB.class);
MockedStatic<ClassC> classCMockStatic = Mockito.mockStatic(ClassC.class)) {
// this is a block where static methods get overwritten, also some mocks are created
// this code does not make sense, it is just to demonstrate the issue of non trivial mocking scenarios
// situations like this often arise when mocking building patterns for example
classAMockStatic.when(ClassA::methodA).thenReturn("fooA");
ClassB classBMock = mock(ClassB.class);
when(classBMock.methodA()).thenReturn("barA");
classAMockStatic.when(ClassA::methodB).thenReturn(classBMock);
ClassC classCMock = mock(ClassC.class);
when(classCMock.someMethodA()).thenReturn("abc");
when(classCMock.methodA()).thenReturn("barA");
classAMockStatic.when(ClassA::methodA).thenReturn(classCMock);
// and so on and so on, you get the idea
result = classX.doSomething();
}
assertThat(result).equals(3);
}
Typically the question arises if this cannot be refactored to implement the mocking cascade only once. And use it in several test cases. I tried that, I was surprised to find that some of my overwritten methods worked as expected, but not all. I failed to find a working solution:
// THIS DOES NOT WORK
#Test
void test_doSomething() {
int result = 0;
ClassX classX = new ClassX();
try (MockedStatic<ClassA> classAMockStatic = createStaticMockA();
MockedStatic<ClassB> classBMockStatic = createStaticMockB();
MockedStatic<ClassC> classCMockStatic = createStaticMockC()) {
result = classX.doSomething();
}
assertThat(result).equals(3);
}
private MockedStatic<ClassA> createStaticMockA() {
MockedStatic<ClassA> classAMockStatic = Mockito.mockStatic(ClassA.class);
classAMockStatic.when(ClassA::methodA).thenReturn("fooA");
ClassB classBMock = mock(ClassB.class);
when(classBMock.methodA()).thenReturn("barA");
classAMockStatic.when(ClassA::methodB).thenReturn(classBMock);
return classAMockStatic;
}
private MockedStatic<ClassB> createStaticMockB() {
MockedStatic<ClassB> classAMockStatic = Mockito.mockStatic(ClassB.class);
ClassB classBMock = mock(ClassB.class);
when(classBMock.someMethodA()).thenReturn("aaa");
when(classBMock.someMethodB()).thenReturn("bbb");
when(classBMock.methodA()).thenReturn("barA");
classBMockStatic.when(ClassB::methodA).thenReturn(classBMock);
return classBMockStatic;
}
private MockedStatic<ClassC> createStaticMockC() {
MockedStatic<ClassC> classAMockStatic = Mockito.mockStatic(ClassC.class);
ClassC classCMock = mock(ClassC.class);
when(classCMock.someMethodA()).thenReturn("abc");
when(classCMock.methodB()).thenReturn("barC");
classCMockStatic.when(ClassC::methodA).thenReturn(classCMock);
return classCMockStatic;
}
So this looks cleared up, but does not work.
I know that I obviously could just extract the mocking section into a method and call that first in the try block. But that separates the static setup from the mock generation. And it is not as clean as my idea.
Yes, I tried implementing an execution method which accepts a lambda holding the code actually meant to be executed. So that the try(){} block gets stowed away into a method, leaving only the call to that method with a lambda in the test case. Works, but is hard to read and to understand. Not a good solution in my experience.
And yes, I also know that one should try to refactor production code so that it is easier to mock it. Sometimes that is simply not possible (read: external dependencies).
So what are my questions here?
does anyone have an idea how to achieve a clean, refactored look which actually works?
can anyone explain to me why some of the overwritten methods work as expected while others don't? I know, all the examples on the internet demonstrate that you use the straight approach, but the examples are obviously showing trivial situations.
is it really true that no one else is annoyed by that situation of have to setup the mock cascade exactly where it confuses? And that you have to reimplement it for each test case?
As Tim Moore suggests, if you have:
class StaticUtil {
public static void foo() { ... }
}
You can introduce an interface and an implementation to inject into your clients:
interface Util {
void foo();
}
class DefaultUtil {
public void foo() {
StaticUtil.foo();
}
This makes writing tests simpler as you can just mock Util in the normal way.

Using power mockito to suppress private static method

I have made a small example of my code to illustrate the problem
public class SiteTranslator {
Integer id;
//Other fields
}
public class SiteUtil {
private static SiteTranslator siteTranslator = getSiteTranslator();
private static SiteTranslator getSiteTranslator()
{
SiteTranslator siteTranslator;
//Logic involving network call
return siteTranslator;
}
private static String getEnvironment()
{
String env = "";
//Logic
return env;
}
public static int getParent(int siteId)
{
int parentId = 0;
//Logic using siteTranslator from getSiteTranslator()
return parentId;
}
}
public class SiteUtilTest {
#Test
public void test1()
{
try
{
PowerMockito.suppress(SiteUtil.class.getMethod("getSiteTranslator"));
BDDMockito.given(SiteUtil.getParent(1)).willReturn(6);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
The SiteTranslator object we get from getSiteTranslator() method is used by my public function getParent(). Since getSiteTranslator() requires a network call , it needs to be suppressed. I however get the following error
java.lang.NoSuchMethodException: SiteUtil.getSiteTranslator()
I believe the problem is because I'm trying to mock a private static function. However I cannot change it to public. Is there a way to mock the code in its current state.
In fact, you don't need Powermockito to achieve what you need.
At the moment, you think you need Powermockito to suppress a private static method but this is definitely not the way to go.
Instead you should refactor your code to make it easier to test:
Remove static qualifiers
Use dependency injection
After such a refactor, you end up with something like that (no mocking needed !):
public class SiteUtil {
private SiteTranslator siteTranslator;
public SiteUtil(SiteTranslator siteTranslator) {
this.siteTranslator = siteTranslator;
}
public int getParent(int siteId) {
int parentId = 0;
// Logic using siteTranslator
return parentId;
}
...
}
Now you can test it like that:
public class SiteUtilSpec {
private final SiteTranslator defaultTranslator = new DummySiteTranslator();
#Test
public void itShouldReturnTheSixthSiteWhenWeProvideTheFirstParent() {
SiteUtil site = new SiteUtil(defaultTranslator);
int parentId = site.getParent(1);
assertEquals(6, parentId);
}
}
DummySiteTranslator is a fake object (maybe it is embedding a bunch of hardcoded translations useful for testing) but the point is that this object never do any network call ! Making its usage safe and fast (ideal for testing).
The answer by "Spotted" already nails it, as the core problem is: you created hard-to-test code for absolutely no reason.
Using such internal static calls simply makes your program hard to test; and surprise: it also makes it hard to maintain, enhance, reuse. The fact that you need to turn to Powermock is very often simply an indication that your production code is bad. Now you can choose between using PowerMock to "fix" that problem; or to really fix the problem, by changing your production code - it is simply bad practice to solve problems the way your example code does!
So, the other real lesson here is: you want to spend some time to learn how to write code that does not have such problems; for example by watching those videos.

Reflection VS static stuff

Recently I've been restructuring a Java code of mines trying to eliminate, wherever possible, static stuff (variables and methods) and replace it with better coding practices.
I also started studying reflection and noticed that it allows me to do some things1 that, at first, I could only achieve (or, at least, that's how I see it) with static calls or references.
However, while I've been reading that the use of static is not much recommended, it doesn't seem to be the same with reflection.
So, I'm asking: instead of making a method static and calling it like ClassName.methodName(), is it a legitimate use of reflection making it an instance method and invoking it by java.lang.reflect.Method.invoke()?
1 like dynamically accessing a class' content
Here's a code sample:
Hypothetic situation that works (but I don't want to make the method static):
import static java.lang.System.out;
public class Foo
{
private static boolean light;
public Foo()
{
turnOn();
}
public static void turnOn()
{
light = true;
}
public static void turnOff()
{
light = false;
}
public static boolean isGreenLight()
{
return light;
}
}
public class Boo
{
public Boo()
{
if (Foo.isGreenLight()) // I need to access Foo.isGreenLight() from here, but cur-
{ // rently that method is not static (it should be to do so)
out.println("Ok!");
}
}
}
public final class Main
{
public static void main(String[] args)
{
final Boo boo = new Boo();
}
}
Hypothetic situation that also should work (how it'd be using reflection):
import static java.lang.System.out;
import java.lang.reflect.Method;
public class Foo
{
private boolean light;
public Foo()
{
turnOn();
}
public void turnOn()
{
this.light = true;
}
public void turnOff()
{
this.light = false;
}
public boolean isGreenLight()
{
return this.light;
}
}
public class Boo
{
public Boo()
{
if ((boolean) Class.forName("Foo").getMethod("isGreenLight", null).invoke(new Foo(), null))
{
out.println("Ok!");
}
}
}
public final class Main
{
public static void main(String[] args)
{
final Boo boo = new Boo();
}
}
Expected output (untested):
Ok!
Using reflection is a code smell, especially if the intent behind what you're writing does not warrant it.
It is difficult to say much more without seeing code as it's all just guesswork.
I would:
enumerate the reasons behind why you had those static members in the first place
determine if the static modifier was in fact the right decision in the first place: i.e. should these be instance or class members? How might they be used by "clients" of the classes in question? What paradigm am I using? Functional or Object Oriented code. Does it satisfy DRY, SOLID and KISS programming practices?
consider if I'm over-engineering in the first place
More importantly:
I would design my code through tests first, which drives the design of your API through the eye of the user, with the added benefit that you have test coverage before you've even implemented. Often times when writing code this way I eliminate such questions because the solution is more obvious when thought from the perspective of a user rather than a designer. It becomes a question of pragmatism rather than satisfying architectural design goals and philosophies.

Static class instance inside class

I am having a difficult time understanding the way static classes are using in the following scenario.
Let’s say I declare a class as follows:
public class TestLibrary {
private static final TestLibrary library = new TestLibrary();
private ErrorHandler errorHandler = null;
public static TestLibrary getLibrary() {
return library;
}
public ErrorHandler getErrorHandler() {
return errorHandler;
}
public int run(String[] args) {
this.initialize(args);
}
private void initialize(String[] data) {
library.errorHandler = new ErrorHandler();
}
}
I now change the class slightly to
private void initialize(String[] data) {
errorHandler = new ErrorHandler();
}
I declare errorHandler in other classes as follows:
private ErrorHandler errorHandler = TestLibrary.getLibrary().getErrorHandler();
My code ultimately still functions the same when I use the instance of errorHandler in other classes, but I don’t understand why.
Question 1: Shouldn’t the 2nd case create a new ErrorHandler that is part of the object TestLibrary.errorHandler rather than library.errorHandler?
Question 2: Am I doing something wrong? Could you elaborate?
What you have there is a static method getLibrary() that returns the same instance for all callers. That's called a Singleton - although there's better ways to code them.
Then again your supposed Singleton (TestLibrary) exhibits methods that when called change internal state - most important, the ErrorHandler.
This will cause strange behaviour, especially in multithreaded systems.
Code like this:
TestLibrary.getLibrary().run("".split(""));
ErrorHandler eh = TestLibrary.getErrorHandler();
assertEquals(eh, TestLibrary.getErrorHandler());
might fail. Because someone (meaning: some other thread) might have just happend to call init() between lines 2 and 3, causing ErrorHandler to be set to just another value.
If you need to initialize your TestLibrary before use, you should do it once, and once only - so you're better of putting this into the constructor of TestLibrary.
If you need TestLibraries that are intialized different throughout your code, you should remove the Singleton pattern and stick to plain
TestLibrary tl = new TestLibrary();
tl.run("".split(""));
Read more about Singleton in What is an efficient way to implement a singleton pattern in Java?

Encapsulating what doesn't vary?

It's a common practice to encapsulate code that often changes. In fact, it is often in the form of using an object to delegate the varying logic to. A sample would be the following:
public class SampleClass {
Object obj = new ObjectWithVaryingMethod();
public SampleClass(Object obj){
this.obj=obj;
}
public String getString(){
return obj.toString();
}
public static void main(String args[]){
SampleClass sampleClass=new SampleClass(new ObjectWithVaryingMethod());
System.out.println(sampleClass.getString());
}
}
class ObjectWithVaryingMethod{
#Override
public String toString(){
return "Hi";
}
}
Can you suggest what problems I may encounter when "encapsulation" is done on what doesn't vary? I find it to be a good coding conduct when the main class itself is the one that is often subject to change or improvement. A sample would be the following. In this second case, retrieving "Hi", which is the part that doesn't vary, was "encapsulated" in another class.
public class SampleVaryingClass {
public static void main(String args[]) {
//here I may opt to print getHi's value on sysout or on a dialog
System.out.println(ObjectWithNonVaryingMethod.getHi());
}
}
In a completely different class...
public class ObjectWithNonVaryingMethod {
private static final String hi = "Hi";
//"Hi" should always be returned
public static String getHi() {
return hi;
}
}
Can you give some pro's and con's on doing this?
Both code cannot be compared each other. One is static, another one isn't. I hope you understand the concept of encapsulating the object in the first code. Here is the pros and cons for the second one. Remember that static is "generally" bad, and do not support concurrency by default.
pros:
With getHi, you are keeping the string field private, meaning that it cannot be set from other source
Say that you need to do setHi from other source, you can add several guard clauses for it. This is called defensive programming.
public static setHi(String input){
if(input == null) { input = ""; } // can throw exception instead
hi = input;
}
cons:
It is static, needless to say
You don't get any advantage other than guard clauses. If your class is not static, you can swap it with other class implementing same interface, or other class inherited from that class.

Categories

Resources