Junit skip call to a function into another question - java

I want to test a function in my code. This function calls another function in the same class but in my test I don't want to call it (I don't need it). Somehow, my test always goes into that inner function and makes errors. Is there any means to "skip" the call to that inner function ?
Here's an example :
void function1() {
if(condition == true) {
variable1 = function2()
}
}
Object function2() {
//Do something
return Object;
}
Is there a way to avoid calling function 2 ?
Thank you.

First you should consider fixing those errors thrown from function2().
If however you want to test the function1() isolated then the behavior you are describing is called Test Doubles. One kind of those test doubles is Mocking where you can drive the behavior of a class or a method.
There are frameworks doing this such as Mockito, but of course you can solve that problem on your own not depending on frameworks.
For example if you use Mockito you should end up mocking the function2() method like this
YouClassName mockedClass = mock(YouClassName.class);
when(mockedClass.function2()).thenReturn(new Object()); //you can of course return anything here
Its pretty common to test functions in isolation but in times where are dependencies between objects. If there are no dependencies you should probably consider not using test doubles (unless you are sure what you are doing).

Frameworks such as Mockito offer concepts such as spies. Using a Mockito spy, you can gain full control over which methods get invoked.
But: you only do that for very specific cases.
When you have a hard time testing your production code, then most likely: because you have written hard to test code.
Thus: you could try to use a spy here, but I would rather advice to step back and re-think what exactly you intend to do here.

Related

Which test double should be used for void method

I'm writing a JUnit test for a method containing the following:
if (p.toString().contains("abc")) {
cCreds(p);
refMgr();
p = new Path(Utils.rmvTkn(p.toString()));
}
cCreds(p); and refMgr(); call void methods. I'm not actually testing these methods but they do get called in the method I am testing so I have to deal with them in some way. I know I need some sort of test double but I'm not sure what. I assume its not with a when().thenReturn(); as nothing is actually returned.
Can anybody advise?
Edit
I should also mention, cCreds(p); and refMgr(); are also private.
Mocking is not necessary the thing to do here.
As these methods :
cCreds(p);
refMgr();
make part of the class under test, you are not compelled to mock them.
Mocking public or private methods of the class under test is not very natural.
It makes generally tests more brittle and less clear.
Mockito provides spy concept to achieve it but it should be favored for legacy code.
In the actual implementation, what you should check is that the method returns or performs a side effect which is expected.
You don't show the whole code of the method, so it is hard to give a more specific pointer.
Note that if these methods :
cCreds(p);
refMgr();
rely some other classes that you need to mock to isolate the component under test, you could refactor your code to extract the method in the dependent classes.
You would invoke them in this way :
foo.cCreds(p);
bar.refMgr();
And you could so mock them easily.
Use doNothing() API from Mockito to mock void methods
doNothing().when(mock).cCreds(p);
doNothing().when(mock).refMgr();
Source: http://www.baeldung.com/mockito-void-methods

Mockito Spy'ing on the object being unit tested

Is it a code smell to spy on an object that is being unit tested? For example say I have a LineCounter class whose job is to simply count the number of lines in a string. --
class LineCounter {
public int getNumLines(String string) {
String metadata = getStringMetadata(string);
// count lines in file
return numLines;
}
/** Expensive operation */
protected String getStringMetadata(String string) {
// do stuff with string
}
}
Now I want to write a JUnit 4 test for this to test the getNumLines method while mocking out the expensive getStringMetadata call. I decide to use Mockito's spy mechanism to have getStringMetadata return a dummy value.
class LineCounterTests {
#Test public void testGetNumLines() {
LineCounter lineCounterSpy = Mockito.spy(new LineCounter());
// Mock out expensive call to return dummy value.
Mockito.when(lineCounterSpy.getStringMetadata(Mockito.anyString()).thenReturn("foo");
assertEquals(2, lineCounterSpy.getNumLines("hello\nworld");
}
}
Is this a reasonable thing to do? I feel pretty weird testing a Spy object rather than the actual class, but I can't really think of a reason against it.
I will answer the question in two parts. First, yes it is code smell to mock or spy the class under test. That does not mean that it cannot be done correctly but that it is risk prone and should be avoided whenever possible.
WRT your specific example, I would see how the spy could be correctly used but that would be predicated on the assertion that you have elsewhere fully unit tested getStringMetadata. This then begs the question, if you have fully unit tested getStringMetadata elsewhere then you must know how to test it and therefore why not test getNumLines without the spy.
All this being said, millhouse makes a good point but either way you have to unit test the expensive code somewhere. His suggestion goes a long way to help isolate the expensive code and ensure that you only have to test / exercise it once.
In this situation, it is perfectly legitimate to stub the method that is called by the method under test. It is even the only way I can think of to test it in isolation. You just don't want to extract a single method into it's own class for the sole purpose of testing.
Beware of the side effects in the stubbed method though. It might not be sufficient to stub the returned value, if the stubbed method has side effects then you have to stub the side effects as well. It might even be a reason against it in some situations where the side effects are very complex, but that would most likely be an indication of a code smell in the implementation of the class under test itself.
To answer your question, I find it easy to find reasons for it, but hard to find reasons against it. It's the technique I use every day, it helps me split my implementation in small methods that are tested individually in complete isolation, and I haven't seen any limitation to it yet.

Can a JUnit test resolve from a object returning a Assertion?

Can a JUnit test resolve from a object returning a Assertion?
For example, if I have a test that looks like this, would this work?
#Test
public void testCase1() {
TestObject to = new TestObject();
to.login();
to.runTest();
// then assert success
to.verifyTest();
}
public Class TestObject() {
....
public Assert verifyTest() {
return assertTrue("Test result not found.", this.validateTestResult() );
}
}
Most Assert calls throw an AssertionError if they fail, so the code wouldn't look exactly the way you put it, but your code could be adjusted slightly and compile/run. Because they are implemented as exceptions, you can call Assert methods from anywhere, including any helper classes you set up to help run your tests easier, as far deep in the stack as you'd like.
EDIT: I do very much recommend setting up helper classes if you need to make a similar set of assertions against many objects. I misunderstood and thought your TestObject was your system under test; the rest applies to that situation instead.
==
There's nothing to prevent you from calling Assert methods from within the class under test, but part of the intention for JUnit is to have clean test classes that are separate from your code classes. That way, the tests can evolve separately and often do not even need to change unless your class's interface changes. In my code, I put them in the same package in a separate "source folder", so you have:
src/com/mypackage/project1/database/DatabaseAccessor.java
testsrc/com/mypackage/project1/database/DatabaseAccessorTest.java
testsrc/com/mypackage/project1/database/DatabaseAccessorSystemTest.java
One of the reasons to separate things this way is to ensure that no testing code is ever run in production; if the verifyTest method is in the same class, there's nothing to stop you from calling it within your class--or worse, from other classes calling it from elsewhere in your codebase. You also avoid depending on junit.jar from production code.
If you are looking to make assertions in production code to avoid inconsistent state or illegal arguments, that's a different matter, and one for which you should avoid JUnit's Assert class--or, for that matter, assert statements (which are compiled out based on arguments to javac). Instead, prefer a library like Guava's Preconditions.

Test smell.... is this good practise?

I have two tests they are exactly the same... barring two things, they call two separate service calls.. hence when im using mockito i have two seperate expectation and verify lines...
this is what i have done:
#test
TestA {
baseTest("player");
}
#test
TestB {
baseTest("member");
}
BaseTest(type type) {
....
.....
if type(player) {
Mockito.when(player service call)
}
else {
Mockito.when(member service call)
}
// make the call in code
//verify
if(player) {
verify player specific service call...
}
else {
}
}
I think the above is a test smell... just doesnt feel right...
Is there a better way then placing an If statement in my baste test?
Anywhere you see repeated if statements like that, you can use polymorphism. You should make the "player service call" and "member service call" methods abstract in the superclass BaseTestSuper, which will also own the existing BaseTest method..
You should develope your test code independenly and join things when they have sense.
By example. One rule of thumb for initialization code (the first A of Arrange/Act/Assert) is that:
you should write all the Arrange part of a test method in the test.
if your method shares initialization with all the other methods, then put it in a #Setup method
if some test method doesn't share that initialization it's probably because it doesn't fit in that test case.
So my conclusion is:
write independent tests
if they share things you can refactor
but not too much (or in a weird thing like "if"s)!!! Adds complexity, not reuse.
In fact #artbristol answer makes sense: if you are using if's for alternate behaviour consider polymorphism. It's just I'm not sure until which point it's complex for test or not (probable it makes sense if the code is testing a similar class hierarchy).
I would still just implement the 2 test classes separately. Code length and duplication don't really matter for tests, code readability, thoroughness and correctness take priority. In that light, just implement the 2 test cases separately.
In general you should not add any complexity to your tests. First, you can make mistake there (even in simple ifs). Second, your tests are not a documentation anymore, meaning that you can not easily understand what is the scenario of usage and behaviour of the tested class.
So it is a smell. :)

unit test best practice for method with mocks in Mockito

Lets say we have method to test in class A that calls method from class B. To test it we created mock for B and then verify if it was called. Is verify(...) enough for unit test or I need assert actual result of tested method?
Below is simplified example to clarify my concern:
public class StringWriterATest {
StringWriterB b = mock(StringWriterB.class);
#Test
public void stringWriterATest() {
StringBuffer sb = new StringBuffer();
StringWriterA a = new StringWriterA();
a.stringWriterB=b;
a.append(sb);
ArgumentCaptor<StringBuffer> argument = ArgumentCaptor.forClass(StringBuffer.class);
verify(b).append(argument.capture());
assertEquals("StringWriterA", ((StringBuffer)argument.getValue()).toString());
//do we really need this or above is enough for proper unit test of method a.append(sb);
//assertEquals("StringWriterA_StringWriterB", sb);
}
}
public class StringWriterA {
public StringWriterB stringWriterB;
public void append(StringBuffer sb) {
sb.append("StringWriterA");
stringWriterB.append(sb);
}
}
class StringWriterB {
public void append(StringBuffer sb) {
sb.append("StringWriterB");
}
}
Regards,
Max
There is never a need to mock a return value and verify an object at the same time.
Consider this:
StringWriterA is the class under test. Therefore you'll definitely want to use assertions to verify the behavior of this class. In order to do this, you mock out a dependency, StringWriterB.
You do not want to test StringWriterB in your test of StringWriterA, therefore any assertions of StringWriterB interactions in your test are in the wrong place.
You must assume that StringWriterB is behaving as expected. You either want to verify that StringWriterA called StringWriterB correctly (using verify()) or you want to mock its expected behavior and mock the return values.
If you mock, then the verify is implicit since the mocked return value will not be returned if the method is not called.
In your case, StringWriterA.append() does not return any value, so only a verify is even possible. That StringWriterB.append() also works should have a similar verify test in a stringWriterBTest of its own.
Note: It's nice to be explicit with tests. Since test methods are never called outside of a framework, there is never a need to type them out, so you can have much longer method names than in production code methods. A nice convention is:
<underTest>Should<Expected>[When]<Condition>()
i.e.
stringWriterAShouldAppendConstantAndDelegateToStringWriterB()
stringWriterAShouldThrowNullPointerExceptionWhenNullArgument()
When you have test failures in your build (continuous integration), then you don't have to hunt down what went wrong, the method name appears right by the failure and you can read it to know exactly what behavior must be fixed.
In your example, StringWriterB stores no state and the append method could easily be static. In that case then the call is purely a side effect and does not need to be tested.
However, I suspect your real code is much more complex. If there is a of another object accessing StringWriterB then you maye want to mock it out in case there are unexpected calls to it. You also may want to add the verify of B if you expect it to be expanded in the future -- possibly storing state from the append call and having accessors.
One thing to consider is what the purpose of the call to StringWriterA.append() is. If it's job is to append the string StringWriterAStringWriterB then that is what you should be testing and a mock is not necessary. How StringWriterA accomplishes that task is immaterial. If, however, part of its job is to also call the StringWriterB.append() method then a mock may will be necessary unless you want to test StringWriterB in A's test.
My rule of thumb WRT mocks is to use real objects until the wiring for the objects I'm not directly testing gets too hairy or too brittle. If I feel like a good portion of my tests are in actuality testing other objects then mocks would be a good idea.
First of all try to show somebody the test you wrote. It is hard to read in my opinion. You can't really tell from it what behaviour you are testing. A brief intro for you how to make it a bit more readable can be found here How to Write Clean, Testable Code .
Using argument captors is also a smell. Some examples how to avoid it can be found on this tdd blog.
To answer you question, verify is used to verify interactions between classes. It is used to drive the design of your code. The result (if needed) should be specified by a when or given at the beginning of your test.
Further information how to drive your design with mocks (when, given, verify, ...) and how mocks are different to stubs can be found here: Mocks are not stubs. That example uses JMock not Mockito for defining mocks, but it is very similar (it is about the concepts, not the details of implementation and libraries you use).

Categories

Resources