How to test a void method with JMock - junit

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.

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.

How do you bypass static method calls?

I have this line which is interferring in a unit test:
OtherClass.staticMethodThatWillErrorIfCalled().isAvailable();
If it wasn't static I could just mock OtherClass and then do this:
Mockito.doReturn(null).when(mockedOtherClass).staticMethodThatWillErrorIfCalled();
Mockito.doReturn(true).when(mockedOtherClass).isGuiMode();
and the fact that it will error if called makes my attempts at using powermockito futile.
I'm not sure how I can do this. All I want to do is skip over this line (it's an if check) and continue on as if it had returned true. What is the best way to do this?
I would require more info to give a more specific answer but this is what I am thinking...
First tell PowerMockito that you will be mocking a static method in OtherClass.
#RunWith(PowerMockRunner.class)
#PrepareForTest(OtherClass.class)
These are class level annotations that go on your unit testing class.
Then mock what to do when that method is called.
PowerMockito.mockStatic(OtherClass.class);
Mockito.when(OtherClass.isAvailable()).thenReturn(Boolean.TRUE);
Do this in your #Before method on your unit testing.

Would it be valid to assert on mockito spyed object?

I am spying an object like:
#Spy
#InjectMocks
private final A a= new A()
and in test case I am asserting on properties of A object.
As spying an object means calling real methods, would it be right to asserting on properties of spyed objects?
Technically it will work, but I recommend against it, it's usually a bad idea (even an anti-pattern) to mock value object.
If the test is to verify properties have changed to specific values then this object is the tested object and as such there would be no reason for it to be a spy.
If creating a simple value object is too difficult with the current API, then there's a usability problem in the tested code, refactoring or utility is needed to create valid instances easily.
Only in some very specific edge cases one would need the combination of a #Spy and #InjectMocks. Most the time it is not needed, and such tests show a design issue in the tested code.
Instead just create a real object, inject mocks if needed and assert properties directly on the tested object. A good spy usage would be verifying that there was interactions between two collaborating objects only.

Why should Test methods in Junit be defined public?

I was going through the documentation for junit tests but am unable to understand the need for defining tests as public.Could anyone share some info on this?
I read on https://github.com/junit-team/junit/blob/master/src/main/java/org/junit/Test.java
But am still not clear with the reason.
With is I meant why can't I write something as
#Test
private void testAdd(){ }
The JUnit framework calls your test methods from outside your test class. If your test methods are private, it won't be able to do that.
"Test classes, test methods, and lifecycle methods are not required to be public, but they must not be private."
Ref. the doc:
https://junit.org/junit5/docs/current/user-guide/#writing-tests-classes-and-methods
JUnit accesses your test methods by reflection. A SecurityManager can control access to private methods. Hence JUnit uses only public methods and fields for anything that is accessed by the framework.
In short: JUnit would fail to run private test methods if a SecurityManager is active that does not allow access to private methods.
try
#Test
public void testAdd(){ }
your testAdd method is private, it won't be able to do that.

Mock methods not directly called in unit test with JMock

I have a method under test. Within its call stack, it calls a DAO which intern uses JDBC to chat with the DB. I am not really interested in knowing what will happen at the JDBC layer; I already have tests for that, and they work wonderfully.
I am trying to mock, using JMock, the DAO layer, so I can focus on the details this method under test. Here is a basic representation of what I have.
#Test
public void myTest()
{
context.checking(new Expectations() {
{
allowing(myDAO).getSet(with(any(Integer.class)));
will(returnValue(new HashSet<String>()));
}
});
// Used only to show the mock is working but not really part of this test.
// These asserts pass.
Set<String> temp = myDAO.getSet(Integer.valueOf(12));
Assert.assertNotNull(temp);
Assert.assertTrue(temp.isEmpty());
MyTestObject underTest = new MyTestObject();
// Deep in this call MyDAO is initialized and getSet() is called.
// The mock is failing to return the Set as desired. getSet() is run as
// normal and throws a NPE since JDBC is not (intentionally) setup. I want
// getSet() to just return an empty set at this layer.
underTest.thisTestMethod();
...
// Other assertions that would be helpful for this test if mocking
// was working.
}
It, from what I have learned creating this test, that I cannot mock indirect objects using JMock. OR I am not seeing a key point. I'm hoping for the second half to be true.
Thoughts and thank you.
From the snippet, I'm guessing that MyTestObject uses reflection, or a static method or field to get hold of the DAO, since it has no constructor parameters. JMock does not do replacement of objects by type (and any moment now, there'll be a bunch of people recommending other frameworks that do).
This is on purpose. A goal of JMock is to highlight object design weaknesses, by requiring clean dependencies and focussed behaviour. I find that burying DAO/JDBC access in the domain objects eventually gets me into trouble. It means that the domain objects have secret dependencies that make them harder to understand and change. I prefer to make those relationships explicit in the code.
So you have to get the mocked object somehow into the target code. If you can't or don't want to do that, then you'll have to use another framework.
P.S. One point of style, you can simplify this test a little:
context.checking(new Expectations() {{
allowing(myDAO).getSet(12); will(returnValue(new HashSet<String>()));
}});
within a test, you should really know what values to expect and feed that into the expectation. That makes it easier to see the flow of values between the objects.