Wanted but not invoked ... Actually, there were zero interactions with this mock - email

I'm doing a little test to an Email sending service
It just a simple JavaMailSender service and i was hoping to make an integration test for it
#SpringBootTest
#ExtendWith(SpringExtension.class)
public class MailingTest {
private JavaMailSender javaMailSender = mock(JavaMailSender.class);
private ArgumentCaptor<MimeMessage> messageCaptor = ArgumentCaptor.forClass(MimeMessage.class);
private Mailing mailing = new Mailing();
#Test
public void sendEmail() throws Exception {
mailing.sendEmail();
verify(javaMailSender).send(messageCaptor.capture());
System.out.println("Result text" + messageCaptor.getValue());
MimeMessage message = messageCaptor.getValue();
message.setSubject("My Subject");
message.setFrom("test#gmail.com");
message.setText("Hello world");
assertThat(message.getSubject()).isEqualTo("My Subject");
assertThat(message.getAllRecipients().toString()).isEqualTo("test#gmail.com");
assertThat(message.getFrom().toString()).isEqualTo("testingSender#gmail.com");
//assertThat(message.getContent()).isInstanceOf(String.class);
assertThat(message.getContent().toString()).isEqualTo("Hello world");
}
}
And i keep getting the following warning and it just stops at the Verify line
been kinda stuck
Wanted but not invoked:
javaMailSenderImpl.send(
<Capturing argument>
);
-> at com.example.demo.MailingTest.sendEmail(MailingTest.java:39)
Actually, there were zero interactions with this mock.
Wanted but not invoked:
javaMailSenderImpl.send(
<Capturing argument>
);

Related

Mock an Interface with Mockito return a NullPointerException

I m trying create unit tests for one project.I m facing a problem because when I try control the result of an interface(mock). When the code get the Interface variable that return a NullPointerException.
Firstly I tried #Override the method in my test class (ClassA), but it don't work. After that I tried mock the interface object and control the comportment with Mockito.When().tehnReturn();
I will put here my code, I read some solutions but none works.
My Interface:
#FunctionalInterface
public interface Interface {
UpdateXResponse process(UpdateXRequest request) throws Exception;
}
The class I want to test:
#Service(ClassA.class)
public class ClassA extends VService implements UpdateX {
#Reference
#Inject
private Interface interface;
#Inject
public ClassA(...) {...}
#Override
public UpdateXResponse process(UpdateXRequest request) throws Exception {
UpdateXResponse response = initResponse(context, request, new UpdateXResponse());
UpdateXInput input = request.getInput();
UpdateXOutput output = new UpdateXOutput();
response.setOutput(output);
try {
firstMethodCall(...);
} catch (Exception t) {
throwCorrectException(t, logger);
}
return response;
}
private void firstMethodCall(...) throws Exception {
TypeF typeF = callInterfaceMethod(...);
...
}
/**
* Orchestrates Interface service
*/
protected TypeF callInterfaceMethod(...) {
...
request.setInput(input);
request.setHeader(header);
InterfaceResponse response = interface.process(request); // LINE ERROR - In this step interface is NULL when the test get this
return response;
}
}
And finally my class test:
#RunWith(PowerMockRunner.class)
#PrepareForTest(value = {ClassA.class,Interface.class} )
public class WithPowerMockUnitTest{
#InjectMocks
private ClassA classA;
private Interface interface;
#Before
public void setUp() throws Exception {
InterfaceRequest InterfaceRequest = createInterfaceRequest();
InterfaceResponse serviceUnavailableResponse = createInterfaceResponse();
Interface = Mockito.mock(Interface.class);
when(Interface.process(Mockito.any(InterfaceRequest.class))).thenReturn(serviceUnavailableResponse);
}
#Test
public void testh() throws SOAException {
InterfaceResponse res = interface.process(Mockito.any(InterfaceRequest.class)); // There all run ok. The interface is not null and return what i expected.
System.out.println("RES "+res);
}
#Test
public void test() {
assertNotNull(classA); // not null
assertNotNull(interface); // not null
}
#Test
public void newTest() throws Exception {
InterfaceRequest InterfaceRequest = createInterfaceRequest();
InterfaceResponse serviceUnavailableResponse = createInterfaceResponse();
UpdateXResponse response = ClassA.process(updateXRequest()); // PROBLEM!! When that get the LINE ERROR the interface is null! WHY?
}
}
I put some comments in the lines where the problem exists for me.
public interface A{
Response process(Request r) throws Exception;
}
public class B{
private Class_That_Override_Interface_method ctoim;
public Response function(){
X res = method_B();
}
protected X method_B(){
response res = ctoim.process(request); // That ctoim is always NULL when the test get that line/call
}
}
Thanks
You're missing the #Mock annotation on your Interface variable.
Therefore the mock is not injected into your classA and the newTest() fails. (In this case remove Interface = Mockito.mock(Interface.class); from the setUp method).
Alternativly remove the #InjectMocks annotation and create your class under test manually passing your mock into the constructor.
For this specific case (assuming its a different case from the last question)
there doesn't seem to be a need to involve PowerMockito. So unless you left out some relevant parts you might as well just use the MockitoJUnitRunner.
Ps.:
Also remeber what I said last time about compilable examples?
interface is a keyword and can't be used for variables.
You should also aim to write variables identical all the times (not Interface and interface / classA and ClassA)
And in case you haven't read it yet check out the help section about minmal reproducible examples.
Edit:
I fogot to mention that the line interface.process(Mockito.any(InterfaceRequest.class)); in testh() is actually invalid syntax. You should use ArgumentMatchers only for parameters of mocked methods.
Also consider adding the MockitoAnnotations.initMocks(this); to your setUp method, when using the PowerMockRunner.

When using MockRestServiceServer cannot precisely test number of service calls

I am coding some retry logic for a service call, and attempting to test that the Rest Template is attempting to hit the service a certain number of times, in a unit test. I am using the following code to perform the test.
MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(ExpectedCount.times(5), method(HttpMethod.GET))
.andRespond(withServerError());
service.call();
I have the retry logic set to only make two attempts. The above test code requires that it occur five times, but the test always passes. In fact, the only way I can get this test to fail is by setting the expected count to one (anything less than the number of actual invocations). The same sort of problem occurs when I use ExpectedCount.min or ExpectedCount.between in that the test will only fail when actual invocations exceed expectation.
I need to be able to test for an exact number of service calls, preferably without the use of Mockito.
This is what finally worked for me, testing with a max attempts of 4:
MockRestServiceServer server;
#Before
public void setUp() {
server = MockRestServiceServer.bindTo(restTemplate).build();
}
#After
public void serverVerify() {
server.verify();
}
#Test
public void doWork_retryThenSuccess() throws Exception {
final String responseBody = "<some valid response JSON>";
final String url = BASE_URL + "/doWork";
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(ExceptionResponseCreator.withException(new SocketTimeoutException("first")));
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(ExceptionResponseCreator.withException(new IOException("second")));
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(ExceptionResponseCreator.withException(new RemoteAccessException("third")));
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
final MyResponseClass response = myService.call();
assertThat(response, notNullValue());
// other asserts here...
}
We are constrained to use Spring Test 5.0.10, which doesn't have MockRequestResponseCreators.withException() (method was added in 5.2.2). Borrowing from Spring 5.2.7 code, this works well:
package com.company.test;
import java.io.IOException;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.test.web.client.ResponseCreator;
import org.springframework.test.web.client.response.MockRestResponseCreators;
public class ExceptionResponseCreator extends MockRestResponseCreators {
public static ResponseCreator withException(IOException ex) {
return request -> { throw ex; };
}
public static ResponseCreator withException(RemoteAccessException ex) {
return request -> { throw ex; };
}
}
You can create your own ResponseCreator with the logic you want. For example:
class DelegateResponseCreator implements ResponseCreator {
private final ResponseCreator[] delegates;
private int toExecute = 0;
public DelegateResponseCreator(final ResponseCreator... delegates) {
this.delegates = delegates;
}
#Override
public ClientHttpResponse createResponse(final ClientHttpRequest request) throws IOException {
ClientHttpResponse ret = this.delegates[this.toExecute % this.delegates.length].createResponse(request);
this.toExecute++;
return ret;
}
}
This delegator executes the ResponseDelegates in order.
So you can mock the response for the call number you want
mockServer.expect(ExpectedCount.times(5), MockRestRequestMatchers.method(HttpMethod.GET))
.andRespond(new DelegateResponseCreator(
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withSuccess()
));
In this example, the first four calls will return a server error whereas the fifth will be a success.
You need to call mockServer.verify() after making all your requests to check if the expectations are met. Otherwise, you can get away with never making any requests.

Capture exception thrown by Hystrix fallback?

I'm designing a service facade and I have a method signature that looks like this:
public Policy getPolicy(long policyId) throws PolicyNotFoundException
If nothing bad happens then a Policy object (simple POJO) is returned. If the requested policy is not found then a checked exception PolicyNotFoundException is thrown (just as a reference - we follow this article when it comes to best practices on exception handling within an application).
The layer above the service facade layer (in this case a Spring MVC RestController) knows how to handle such a PolicyNotFoundException and return an appropriate payload.
I'm trying to incorporate this into a HystrixCommand by doing something like this:
#HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe", ignoreExceptions = { PolicyNotFoundException.class })
public Policy getPolicy(long policyId) throws PolicyNotFoundException {
LOGGER.info("Getting policy {}", policyId);
// Simulate some error condition for testing purposes
throw new RuntimeException("Something happened!");
}
private Policy getPolicySafe(long policyId, Throwable t) throws PolicyNotFoundException {
LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId, t);
throw new PolicyNotFoundException(policyId);
}
Basically I want my circuit breaker to simply behave as if the policy wasn't found by the original lookup. The problem I'm having with this though is the exception I throw from the fallback method is getting lost in translation somewhere. The exception I end up seeing in the layer above is the RuntimeException thrown by the command method and not the exception thrown by the fallback method. Is there a way around this? I don't want to change the contract of my original method either nor do I want the layer above this to know anything other than to have to catch PolicyNotFoundException in the case a policy isn't found. Whatever is needed here should be captured within this service facade layer.
Any and all help would be greatly appreciated. Thanks!
So based on the link #spencergibb gave - I may have found a solution after upgrading to Hystrix 1.5.7. This code works as expected
PolicyRestController.java
#RestController
#RequestMapping("/policies")
public class PoliciesApi {
private static final Logger LOGGER = LoggerFactory.getLogger(PoliciesApi.class);
#Autowired
private PolicyService policyService;
#RequestMapping(value = "/{policyId}", method = RequestMethod.GET, produces = { MediaTypes.POLICY_JSON_VALUE, MediaTypes.POLICY_XML_VALUE })
public Policy getPolicy(#PathVariable long policyId) {
try {
// This just shown for simplicity. There is more to this method (input validation/etc)
return this.policyService.getPolicy(policyId);
}
catch (PolicyNotFoundException ex) {
// NotFoundException is a RuntimeException annotated with #ResponseStatus(HttpStatus.NOT_FOUND)
// So the service returns a 404 to the client
LOGGER.info("Policy {} wasn't found", ex.getPolicyId(), ex);
throw new NotFoundException(String.format("Policy %s was not found", ex.getPolicyId()));
}
}
}
PolicyService.java
public interface PolicyService {
#Cacheable("allPolicies")
public List<Policy> getPolicies();
#Cacheable("policies")
public Policy getPolicy(long policyId) throws PolicyNotFoundException;
}
PolicyServiceImpl.java:
#Service
public class PolicyServiceImpl implements PolicyService {
#HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe", ignoreExceptions = { PolicyNotFoundException.class })
public Policy getPolicy(long policyId) throws PolicyNotFoundException {
LOGGER.info("Getting policy {}", policyId);
// Simulate some error condition for testing purposes
throw new RuntimeException("Something happened!");
}
#HystrixCommand(groupKey = "PolicyService", ignoreExceptions = { PolicyNotFoundException.class }, raiseHystrixExceptions = { HystrixException.RUNTIME_EXCEPTION })
private Policy getPolicySafe(long policyId) throws PolicyNotFoundException {
// Here is we hit our fallback we want to log a warning & simply act as if the policy wasn't found by throwing the same contingency exception as the API does
LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId);
throw new PolicyNotFoundException(policyId);
}
}
While your solution might work for you I've noticed some weirdness in your code (I can't check my assumptions so I would like to ask you to check this).
Try to avoid using checked exceptions in your code because it's
awkward to maintain.
Based on your code you will never catch
"PolicyNotFoundException" since you're using raiseHystrixExceptions = { HystrixException.RUNTIME_EXCEPTION } which means that you won't to get your custom exception so that HystrixRuntimeException will be propagated. Try to rewrite your code as follows so it should
simplify the code and maybe fix some of your problems:
#Service
public class PolicyServiceImpl implements PolicyService {
#HystrixCommand(groupKey = "PolicyService", fallbackMethod = "getPolicySafe")
public Policy getPolicy(long policyId) throws PolicyNotFoundException {
LOGGER.info("Getting policy {}", policyId);
throw new PolicyNotFoundException(); // throw real PolicyNotFoundException if policy is absent for the given id
}
#HystrixCommand(groupKey = "PolicyService")
private Policy getPolicySafe(long policyId) throws PolicyNotFoundException {
// Here is we hit our fallback we want to log a warning & simply act as if the policy wasn't found by throwing the same contingency exception as the API does
LOGGER.warn("Falling back to circuit-breaker for getting policy {}", policyId);
throw new PolicyNotFoundException(policyId);
}
}
This is the default behavior of hystrix. "If command has a fallback then only first exception that trigers fallback logic will be propagated to caller"
See the error propagation section here.
I do this:
#Component
public class HystrixClient {
#HystrixCommand(ignoreExceptions = {ClientArgumentException.class})
public POJO getPojo(String id)
throws ClientNoDataFoundException, ClientArgumentException, ClientGeneralException {
//call my service and return POJO
}
}
#Component
public TrueClientUsedForAnotherSerivce {
#Autowired
HystrixClient hystrixClient;
public POJO getPojo(String id)
throws ClientNoDataFoundException, ClientArgumentException, ClientGeneralException, ClientOpenCircuitException {
try {
POJO result = hystrixClient.getCellular(id);
return result;
}
catch(HystrixRuntimeException e) {
LOG.debug("The circuit is open");
throw new ClientOpenCircuitException("Open circuit");
}
}
It only works if #HystrixCommand method is in another class.

Timer in Drools Fusion not working

I am trying to run following rules in Drool Fusion( Version 5.4.1 ), but it's not working.
Ideally it should print "HELLO WORLD" every 7 seconds, it's not even triggering once.
Can anybody please help me to understand the timer in Drools?
import com.drools.message.Message
rule "Test"
timer(int: 7s 7s)
when
message:Message (type=="Hello")
then
System.out.println("Hello World, Drools! " + message.getMsgtext());
end
My code to run the above Rule is:
public class TestDrools {
private static String DRL_FILE = "test_drools.drl";
private static KnowledgeBuilder kbuilder = KnowledgeBuilderFactory
.newKnowledgeBuilder();
private static Collection pkgs;
private static KnowledgeBase kbase = KnowledgeBaseFactory
.newKnowledgeBase();
private static StatefulKnowledgeSession ksession;
private static WorkingMemoryEntryPoint entryPoint;
public static void main(String[] args) {
init();
while (true) {
Message msg = new Message();
msg.setType("Hello");
msg.setMsgtext("1");
ksession.insert(msg);
}
}
private static void init() {
initialiseDrools();
}
private static void initialiseDrools() {
kbuilder.add(ResourceFactory.newClassPathResource(DRL_FILE),
ResourceType.DRL);
if (kbuilder.hasErrors()) {
System.out.println(kbuilder.getErrors().toString());
throw new RuntimeException("Unable to compile drl\".");
}
pkgs = kbuilder.getKnowledgePackages();
KnowledgeBaseConfiguration config = KnowledgeBaseFactory
.newKnowledgeBaseConfiguration();
config.setOption(EventProcessingOption.STREAM);
kbase = KnowledgeBaseFactory.newKnowledgeBase(config);
kbase.addKnowledgePackages(pkgs);
KnowledgeSessionConfiguration conf = KnowledgeBaseFactory
.newKnowledgeSessionConfiguration();
conf.setOption(ClockTypeOption.get("pseudo"));
ksession = kbase.newStatefulKnowledgeSession(conf, null);
entryPoint = ksession.getWorkingMemoryEntryPoint("entryone");
new Thread() {
#Override
public void run() {
ksession.fireUntilHalt();
}
}.start();
}
}
Thank you
-Sanjay
As per #laune's comment, you've used the pseudo clock. If you want to use the realtime clock, change the following line:
conf.setOption(ClockTypeOption.get("realtime"));
Or just remove the line altogether - realtime is the default clock.
If you want to use the pseudo clock, you'll need to advance it yourself. This is typically use in unit testing, e.g.
SessionPseudoClock clock = ksession.getSessionClock();
// insert some facts ...
clock.advanceTime(1, TimeUnit.HOURS);
ksession().fireAllRules();
// Do your unit test asserts / verify mocks here to verify that
// time-reasoned rules were / weren't fired
then condition happens when when condition fulfills,so you need to at least put eval(true) in when condition and trigger an insert into knowledgeSession so that the rule engine figure out what to do when some condition fulfills.

Gwt Logging into Client UI from Server-side

I have created GWT app, in which I have a Vertical Panel where I log the details.
Client side logging I'm doing using logger
sample code is:
public static VerticalPanel customLogArea = new VerticalPanel();
public static Logger rootLogger = Logger.getLogger("");
logerPanel.setTitle("Log");
scrollPanel.add(customLogArea);
logerPanel.add(scrollPanel);
if (LogConfiguration.loggingIsEnabled()) {
rootLogger.addHandler(new HasWidgetsLogHandler(customLogArea));
}
And I'm updating my vertical log panel using this code
rootLogger.log(Level.INFO,
"Already Present in Process Workspace\n");
But now my question is , I have to log server side details also into my vertical log panel.
My serverside GreetingServiceImpl code is:
public boolean createDirectory(String fileName)
throws IllegalArgumentException {
Boolean result = false;
try {
rootLogger.log(Level.INFO,
"I want to log this to my UI vertical log Panel");
system.out.println("log this to UI");
File dir = new File("D:/GenomeSamples/" + fileName);
if (!dir.exists()) {
result = dir.mkdir();
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
Now I want to log sysoutprt statements to my UI from here. How can I achieve this. Now using rootLogger.log(Level.INFO,
"I want to log this to my UI vertical log Panel"); code it is logging this to eclipse console . But how to log this to my UI in client side.
Please let me know If anything wrong in this question.
If I understood you right, you want to see your server log entries in web interface. And of course, java logger and printStackTrace() won't help you in that: your gwt code is compiled to JavaScript and has nothing to do with console and log files. Besides, your server can't "push" log entries to client - it's up to client to make requests. So if you want to track new log entries and move it to client, you need to poll server for new entries. And yet another problem: you may have many clients polling your servlet and you should keep in mind this multi-threading.
This is how I see probable implementation (it's just concept, may contain some errors and misspellings):
Remote interface:
public interface GreetingService extends RemoteService {
List<String> getLogEntries();
boolean createDirectory(String fileName)throws IllegalArgumentException;
}
Remote Servlet:
public class GreetingServiceImpl extends RemoteServiceServlet implements GreetingService {
public static final String LOG_ENTRIES = "LogEntries";
public List<String> getLogEntries() {
List<String> entries = getEntriesFromSession();
List<String>copy = new ArrayList<String>(entries.size());
copy.addAll(entries);
//prevent loading the same entries twice
entries.clear();
return copy;
}
public boolean createDirectory(String fileName)throws IllegalArgumentException {
Boolean result = false;
try {
log("I want to log this to my UI vertical log Panel");
log("log this to UI");
File dir = new File("D:/GenomeSamples/" + fileName);
if (!dir.exists()) {
result = dir.mkdir();
}
} catch (Exception e) {
log("Exception occurred: " + e.getMessage());
}
return result;
}
private List<String> getEntriesFromSession() {
HttpSession session= getThreadLocalRequest().getSession();
List<String>entries = (List<String>)session.getAttribute(LOG_ENTRIES);
if (entries == null) {
entries = new ArrayList<String>();
session.setAttribute(LOG_ENTRIES,entries);
}
return entries;
}
private void log(String message) {
getEntriesFromSession().add(message);
}
Simple implementation of polling (gwt client-side):
Timer t = new Timer() {
#Override
public void run() {
greetingAsyncService.getLogEntries(new AsyncCallBack<List<String>>() {
void onSuccess(List<String>entries) {
//put entries to your vertical panel
}
void onFailure(Throwable caught){
//handle exceptions
}
});
}
};
// Schedule the timer to run once in second.
t.scheduleRepeating(1000);
greetingAsyncService.createDirectory(fileName, new AsyncCallBack<Void>(){
void onSuccess(List<String>entries) {
//no need to poll anymore
t.cancel();
}
void onFailure(Throwable caught){
//handle exceptions
}
});
}
As you can see, I have used session to keep log entries, because session is client-specific and so different clients will receive different logs. It's up to you to decide what to use - you may create your own Logger class that will track users itself and give appropriate logs to appropriate clients.
And also you may want to save level of your messages (INFO,ERROR etc.) and then display messages in different colors (red for ERROR, for instance). To do so, you need to save not List, but some your custom class.
You'd create a logging servlet that has the same methods as your logging framework to send log messages to your server via RPC.
Here are some sample RPC log methods you can use:
public interface LogService extends RemoteService {
public void logException(String logger, String priority, String message, String error, StackTraceElement[] stackTrace, String nativeStack);
}
public interface LogServiceAsync {
public void logException(String logger, String priority, String message, String error, StackTraceElement[] stackTrace, String nativeStack, AsyncCallback<Void> callback);
}
public class LogServiceImpl extends RemoteServiceServlet implements LogService {
public void logException(String loggerName, String priority, String logMessage, String errorMessage, StackTraceElement[] stackTrace, String nativeStack) {
Logger logger = getLogger(loggerName);
Level level = getLevel(priority);
// Create a Throwable to log
Throwable caught = new Throwable();
if (errorMessage != null && stackTrace != null) {
caught = new Throwable(errorMessage);
caught.setStackTrace(stackTrace);
}
//do stuff with the other passed arguments (optional)
logger.log(level, message, caught);
}
}
Although those implementations are very nice, forget about timers and repeated server queries. We've something better now.
It's possible to push data from server to client using Atmosphere which supports WebSockets.