writing tests for method that calls methods from same class - junit

I have the following class, and I've tested method1 having method2 and method3 mocked. I only test cases like:
* if method2 call is OK then ==> OK
* if method2 throws NotFoundException and method3 returns OK ==> OK
* if method2 throws NotFoundException and method3 throws ServiceException ==> ServiceException is indeed thrown
Is it ok to mock methods method2 and method3 in order to test just the functionality of method1? I've also added separate tests for method2 and method3, so I know they are fully working.
class ClassUnderTest {
public void method1() {
try {
method2();
} catch (NotFoundException e) {
method3()
}
}
public void method2() throws NotFoundException {
...
}
public void method3() throws ServiceException {
...
}
}

You CAN do what you're suggesting, using a Mockito spy, which allows you to stub some methods but not others. However, it's often not the best thing to do. The reason is this.
Any sort of test of a method should be testing the behaviour of that method - what its outputs are, what its side effects are, and whether there's any special behaviour due to variation in inputs. Your test really shouldn't care what the implementation of a method is, provided it has the right behaviour. So even though method1 calls method2 and method3, it's not a requirement of the class that it has been implemented that way. So instead of a test that asserts that method1 calls method2, your test for method1 should not mention method2 at all - it should merely check that the outputs and/or side effects of method1 are what they are supposed to be.
It does mean that you might have some duplicated assertions between your tests for method1 and your tests for method2, but balancing that is the fact that your tests will be robust against changes of implementation.

It depends on the granularity you want to give to your tests.
A convention could be just mock methods of other clasees in order to make the test cases easier to be written, but in some situations perhaps you have to write mocks for methods on the same class, for example, if you want to simulate an error in the method2 it is ok to mock it.
Always you should try to keep your tests as easy as possible.

Related

Mockito - Function calls other function, should I mock both?

I have a code with two methods. Method A is calling method B. Should I mock method B? Or can I let method A call method B since there it's only buciness logic without datatabase connection or httprequests?
public Response InsertAsset(UpdateRequest apiRequest, String token) throws IOException, InterruptedException
{
/* TODO
* Change hard-coded URL implementation
*/
String url = "http://test:8080/update";
User user = userRepository.findByToken(token);
UpdateRequestRequest = new UpdateRequest();
generateRequestAPI(Request, user);
Request.setAsset(apiRequest.getAsset());
Request.setKey(generateCombinedKey(Request, user));
// Will throw NullPointerException in case HTTP body cannot be generated
HttpRequest httpRequest = generateHttpPostRequest(url, Request, token);
HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
return objectMapper.readValue(httpResponse.body(), Response.class);
}
Edited because I had gotten the question wrong at first.
Short answer is: you may probably just use the generateHttpPostRequest().
Longer answer ...
The original answer:
Without knowing your code an answer is impossible. Mocks are for unit tests. In a unit test you have the system under test (SUT) and external dependencies. For a unit test you want to get rid of all behaviour in the dependecies and instead completely control what you SUT will see during the test. Also unit tests must be easy to read, hence complex configurations are a no.
Some hints for your decision:
Never mock the SUT!
If the dependency has no behaviour and you can easily determin what state it will present your SUT, you may not need to mock it.
Configuring a mock to return a mock may be needed sometimes but generally should be avoided, if possible.

Is there a way to share #Before code between tests suite classes?

I am testing a Cordova plugin in Java/Android and I need to initialize my Plugin class and set some state before I run my Tests.
#Before
public void beforeEach() throws Exception {
System.out.println("Creating new Instance ");
PowerMockito.mockStatic(Helpers.class);
PowerMockito.when(Helpers.canUseStorage(any(), any())).thenReturn(true);
MyLogger myLoggerMock = PowerMockito.mock(MyLogger.class);
PowerMockito.doNothing().when(myLoggerMock, "log", anyString());
PowerMockito.whenNew(MyLogger.class).withAnyArguments().thenReturn(myLoggerMock);
this.sut = spy(new FilePicker());
PowerMockito.doNothing().when(this.sut).pick(any(), any());
}
I want to create a Test Suite / Java Class per public function, but I do not want to repeat that code every time.
Is there a way to share that before each between test suites? I have found ClassRule but I think I do not do what I need (or I am understanding it wrong... I am really new in Java)
In Typescript we can share beforeEachfunctions with several suites, and each suite can have their own beforeEach
One possible ways is using inheritance:
Make all test classes extend from one "parent test" class and define a #Before in a parent class.
So it will be called automatically for all the subclasses:
public class ParentTest {
#Before
public void doInitialization() {
....
}
}
public class Test1Class extends ParentClass {
#Test
public void fooTest() {
// doInitialization will be executed before this method
}
#Test
public void barTest() {
// doInitialization will be executed before this method as well
}
}
Two notes:
Note 1
In the code you use sut (subject under test) - this obviously should not be in the parent's doInitialization method, so its possible that Test1Class will also have methods annotated with #Before (read here for information about ordering and so forth)
Then the `sut gets initialized with Spy which is frankly weird IMHO, the Subject Under Test should be a real class that you wrote, but that's beyond the scope of the question, just mentioning it because it can point on mistake.
Note 2
I'm writing it in an an attempt to help because you've said that you're new in Java, this is not strictly related to your question...
While this approach works in general you should be really cautious with PowerMockito. I'm not a PowerMockito expert and try to avoid this type of mocks in my code but in a nutshell the way it manipulates the byte code can clash with other tools. From your code: you can refactor the HelperUtils to be non-static and thus avoid PowerMocking in favor of regular mocking which is faster and much more safe.
As for the Logging - usually you can compromise on it in unit test, if you're using slf4j library you can config it to use "no-op" log for tests, like sending all the logging messages into "nothing", and not-seeing them in the console.

How can you unit test Apache Cache Timer routes?

Using Apache Camel 2.9.1
How do I unit test something like the following?
public class MyRoute extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer.something?delay=0?repeatCount=1")
// do some stuff
.to("{{some.endpoint}}")
.end()
from("timer.somethingelse?delay=3000&period=1000")
// do some stuff
.to("{{some.other.endpoint}}")
.end
}
}
What is exactly that you want to unit test here?
Because it's clueless to unit test the timer component (I mean to unit test if it's triggered or not; and if its properties works as it should be): Camel team has done that already.
What is logical to unit test here is the "// do some stuff" part, which you'd do by mocking the endpoints. Your first route will be fired automaticly, while the second will with initial delay. You'll have to wait that much at least to assert anything. In these kind of cases I usually read the endpoint properties from a properties files like
from("timer:somethingelse?{{2nd.timer.properties}}")
and that can be set to
2nd.timer.properties=delay=3000&period=1000 //in prod
2nd.timer.properties=delay=0 //during tests
So that one is triggered at startup as well. Hope that helps,
Gergely
You can also use advice with in your unit test, and replace the from endpoint uri in the route during testing, and for example use a direct endpoint, then you can send a message to the direct endpoint to trigger the route to run.
See details at the Camel docs about testing
http://camel.apache.org/testing
http://camel.apache.org/advicewith.html
And there is also NotifyBuilder which can be used for "black box testing" where you may assert that X messages was processed etc
http://camel.apache.org/notifybuilder.html

Why Exception inside a method should be handled within the method itself and not outside?

Consider a method() that throws some exception in its body.
Consider the following scenarios:
Scenario 1:
{
//..
// ..
method(); //Exception handled inside the method
//..
//..
}
In this case the exception should be handled within the method() itself.
Also consider this:
Scenario 2:
{
//..
//..
try{
method(); //Exception not handled with-in the method
}
catch(){}
//..
// ..
}
Why a situation like scenario 2 is not allowed? ie why it is forced that the exception should be handled within the method?
You can add throws clause to your method and make it throw an exception, which can be handled, as mentioned in Situation 2. So its allowed, like this:-
void method() throws Exception{
}
Both scenarios are allowed. The restriction (if that's the right term) that Java imposes is that the exception must be handled somewhere.
In the first scenario, the called method handles the exception itself - so there's no need for the try-catch in the calling method.
The second scenario is valid - but only if method() includes the throws declaration to indicate that the exception must be handled somewhere else.
void method() throws Exception
{
}
It is allowed!
use as follows
public void method() throws ClassNotFoundException {
to catch a ClassNotFoundException.
(In most cases you should not throw a bare Exception, like other posters simplified)
Whether to chatch inside or outside is software design. There is no rule of thumb.
My experience is that catching outside leads to less complex code, which can be better unit tested .
Look for design pattern "last line of defense":
That means that in your top most class e.g in main() there is a catch (Exception ex) {
which catches when no other method catched it. in that case you can log the exception and (try to) safely shut down your system. This is the last line of defense.
Note: spmetimes it also makes sense to catch(Throweable th),
If you handle exception using senario-2, then cannot map the exception to the actual one. i.e you cannot state it as per the code in block. So please handle the exception to the spot itself, so that you can specifically explain why the exception has occurred.
As said above, the idea is to throw early and catch late. Overall, you want to minimize exceptions you throw by simply making your logic "flow". But there are always situations which are tricky to handle, or obfuscate code too much, so it is worth ensuring the user understands the risks of using certain methods and handles them accordingly.
TL;DR: Never trap InterruptedException unless you really mean to. It almost always needs to be thrown.
This great question is actually a very important design decision. Getting this right is difficult and getting this right across an entire team is even more difficult. The answer to the question lies within your implementation. Does the error need to be immediately shown to the user? Do you have an auxiliary method to recover from the failure? Is the exception a fatal event?
Please do yourself a favor and never write an empty exception handler. You will be very happy to have put in a log.debug statement in there when things go awry. Other than that: learn what every exception means and respond to it in the most graceful way possible.

How to test a void method with JMock

How to test a void method i.e. method that doesn't return anything in JMock?
To test a method that doesn't return anything, regardless of the testing or mocking framework you're using, you test the effect of a call to the method.
With JMock that likely means that you create a mock of something the code you're testing should call, set things up so that your mock is used instead of a real object, and set and verify expectations for calls to that mock.
I might be able to get more specific if you can add specifics to your question.
void methods generally make some changes in the value of the fields of the class. If the field of the class is not private then you can access it in your test class after calling the void method in your test method to assert if you are getting the expected value.