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

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.

Related

Programmatically instantiate a FeignClient for tests

I have a dead simple FeignClient interface that I would like to "unit"/integration test with a fake HTTP server, WireMock for example. The idea is to test the mapping with a sampled HTTP API response, without configuring a whole Spring Boot/Cloud Context.
#FeignClient(name = "foo", url = "${foo.url}")
public interface FooClient {
#RequestMapping(value = "/foo/{foo-id}/bar", method = RequestMethod.GET)
public Bar getBar(#PathVariable("foo-id") String fooId);
}
Is there any way to programmatically instantiate this interface, like a Spring Data Repository through a *RepositoryFactoryBean ?
I see a FeignClientFactoryBean in the source code, but it is package protected, and it relies on an ApplicationContext object to retrieve its dependencies anyway.
Well, you can fake a real rest client using wiremock for testing purposes, but this is more about containing the functional test, that feign clients themself work. This is mostly not what you really want to test, because the actual need is to test your components using your client behave in a specified way.
The best practice for me is not to make live hard with maintaing a fake server, but mock the clients behavior with Mockito. If you use Spring Boot 1.4.0, here is the way to go:
Consider you have some FooBarService, which internally uses your FooClient to peform some FooBarService::someAction(String fooId), which performs some business logic which needs to work with a foo with given id
#RunWith(SpringRunner.class)
#SpringBootTest(classes = App.class)
class FooUnitTest {
#Autowired;
private FooBarService fooBarService;
#MockBean;
private FooClient fooClient;
#Test
public void testService() {
given(fooClient.getBar("1")).willReturn(new Bar(...));
fooBarService.someAction("1");
//assert here, that someAction did what it supposed to do for that bar
}
}
At this point you first should clarify, what you expect the REST client to respond, when asking for "/foo/1/bar", by creating a mock for exactly that case and give the Bar object you expect to receive for that API, and assert that your application is in the desired state.

Mule: JUnit test case to call a service which is in middle of the Mule flow

I'm newbie for JUnit test case. Please help me on this issue. I have 2 mule flows- first flow having MQ as inbound and it has datamapper to transformer the xml. With the first flow input, i'm calling second flow where we are calling the existing service ( SOAP/HTTP) call. Please find my JUnit below. I'm able to get the success response. But my requirement
1. I need to see the transformer response coming out from the Transformer.( Like how we see via logger component in our flow)
2.Need to override the url (HTTP) through JUnit ( in order to test the error scenario)
public class Request_SuccessPath extends FunctionalTestCase {
#Test
public void BulkRequest () throws Exception {
MuleClient client = muleContext.getClient();
System.out.println("test");
String payload = " <root> <messageName>str1234</messageName><messageId>12345</messageId><DS>123</DS><</root>";
MuleMessage reply = client.send ("vm://test",payload ,null);}
#Override
protected String getConfigResources() {
// TODO Auto-generated method stub
return "src/main/app/project.xml";}
i thought the following snippet will override the url.But it is not
DefaultHttpClient client1 = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("http://localhost:7800/service);
assertNotNull(response);
3. How to take the control of the flow and see any response inbetween the flow.
Instead of WMQ, i have replaced VM as inbound end point for testing purposes.
4. Is there any chance like without replacing VM can we call directly with WMQ through JUnit TestCase. Kindly help me on this.
I'm using 3.4 version, not using maven as of now. Please help me. Thanks in advance.
1) What do you mean by "see". Would it work logging it? inspecting it while debugging?
2) You should parametrize your endpoint with a variable, something like
and configure a property placeholder as explained here: http://www.mulesoft.org/documentation/display/current/Using+Parameters+in+Your+Configuration+Files
Adding http.port, http.host and http.path variables to mule-app.properties
taking into account that you must set system-properties-mode="OVERRIDE" and then start your Mule server using bin/mule -M-Dhttp.host=your-host -M-Dhttp.port=your-port -M-Dhttp.path=your-path
3) Yes, WMQ has a Java API you can use to interact with it: http://publib.boulder.ibm.com/infocenter/wmqv6/v6r0/index.jsp?topic=%2Fcom.ibm.mq.csqzaw.doc%2Fuj41013_.htm , you will probably found hundreds of examples by googling about it.
Regards.

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

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.

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.