Files/Paths/FileUtils - Mock several static classes in one test - path

I have to mock the below method:
public static void cleanAndCreateDirectories(#NonNull final Path path) throws IOException {
// If download directory exists(should not be symlinks, clear the contents.
System.out.println(path);
if (Files.exists(path, LinkOption.NOFOLLOW_LINKS)) {
System.out.println("lol");
FileUtils.cleanDirectory(path.toFile());
} else {
// Eager recursive directory creation. If already exists then doesn't do anything.
Files.createDirectories(path);
}
}
I have tried doing like this but it doesn't work:
#Test
public void cleanAndCreateDirectoriesPathExistsHappyCase() throws IOException {
PowerMockito.mockStatic(Paths.class);
PowerMockito.when(Paths.get("/dir/file")).thenReturn(FileSystems.getDefault().getPath("/dir/file"));
PowerMockito.mockStatic(Files.class);
PowerMockito.when(Files.exists(Paths.get("/dir/file"), LinkOption.NOFOLLOW_LINKS)).thenReturn(true);
File file = new File("/dir/file");
Mockito.when(Paths.get("/dir/file").toFile()).thenReturn(file);
PowerMockito.mockStatic(FileUtils.class);
ArsDumpGeneratorUtil.cleanAndCreateDirectories(Paths.get("/dir/file"));
}
I am getting following exception message:
File cannot be returned by get()
[junit] get() should return Path
Am I doing something wrong? Please tell me the best practice for this.

Solved as follows:
#Test
public void cleanAndCreateDirectoriesPathExistsHappyCase() throws IOException {
PowerMockito.mockStatic(Files.class);
PowerMockito.when(Files.exists(Paths.get("/dir/Exist"), LinkOption.NOFOLLOW_LINKS)).thenReturn(true);
// Mock FileUtils.
PowerMockito.mockStatic(FileUtils.class);
PowerMockito.doNothing().when(FileUtils.class);
// Call internal-static method.
FileUtils.cleanDirectory(Matchers.any());
// Call target method.
ArsDumpGeneratorUtil.cleanAndCreateDirectories(Paths.get("/dir/Exist"));
// Check internal-static method call.
PowerMockito.verifyStatic(Mockito.times(1));
FileUtils.cleanDirectory(Matchers.any());
}
#Test
public void cleanAndCreateDirectoriesPathNotExistsHappyCase() throws IOException {
PowerMockito.mockStatic(Files.class);
PowerMockito.when(Files.exists(Paths.get("/dir/NotExist"), LinkOption.NOFOLLOW_LINKS)).thenReturn(false);
PowerMockito.when(Files.createDirectories(Paths.get("/dir/NotExist"))).thenReturn(Paths.get("/dir/NotExist"));
// Call target method.
ArsDumpGeneratorUtil.cleanAndCreateDirectories(Paths.get("/dir/NotExist"));
// Check internal-static method call.
PowerMockito.verifyStatic(Mockito.times(1));
Files.createDirectories(Matchers.any());
}

Related

How to change constructor arguments?

I have a record that performs a verification in its constructor as such :
public record Configuration(URI url) {
public Configuration(URI url) {
Validate.httpValid(url, "url");
}
}
Where the httpValid method is :
public static URI httpValid(final URI value, final String property) {
try {
value.toURL();
} catch (IllegalArgumentException | MalformedURLException e) {
throw new InvalidPropertyValueException(property, "httpValid", value, Map.of());
}
return value;
}
This however fails the test i'm trying to create :
#Test
void Should_RespectEqualsContract() {
EqualsVerifier
.forClass(Configuration.class)
.withPrefabValues(
Configuration.class,
new Configuration(URI.create("http://a.com")),
new Configuration(URI.create("http://b.com")))
.verify();
}
This is because EqualsVerifier is trying to create an object with "x" as argument :
InvalidPropertyValueException: The value x is not a valid httpValid as url
You're very close. You shouldn't provide the class that you're testing as a prefab value; instead you need to provide the paramter that's causing trouble, like this:
#Test
void Should_RespectEqualsContract() {
EqualsVerifier
.forClass(Configuration.class)
.withPrefabValues(
URI.class,
URI.create("http://a.com"),
URI.create("http://b.com"))
.verify();
}

SpringAMQP errorHandler and returnExceptions problem

i am not sure my understanding to errorHandler and returnExceptions is right or not.
but here is my goal: i sent a message from App_A, use #RabbitListener to receive message in App_B.
according to the doc
https://docs.spring.io/spring-amqp/docs/2.1.3.BUILD-SNAPSHOT/reference/html/_reference.html#annotation-error-handling
i assume if APP_B has a business exception during process the message,through set errorHandler and returnExceptions in a right way on #RabbitListener can let the exception back to App_A.
do I understood correctly?
if i am rigth, how to use it in a right way?
with my code, i get nothing in APP_A .
here is my code in APP_B
errorHandler:
#Component(value = "errorHandler")
public class ErrorHandler implements RabbitListenerErrorHandler {
#Override
public Object handleError(Message arg0, org.springframework.messaging.Message<?> arg1,
ListenerExecutionFailedException arg2) throws ListenerExecutionFailedException {
throw new ListenerExecutionFailedException("msg", arg2, null);
}
}
RabbitListener:
#RabbitListener(
bindings = #QueueBinding(
value = #Queue(value = "MRO.updateBaseInfo.queue", durable = "true"),
exchange = #Exchange(name = "MRO_Exchange", type = ExchangeTypes.DIRECT, durable = "true"),
key = "baseInfoUpdate"
),
// errorHandler = "errorHandler",
returnExceptions = "true"
)
public void receiveLocationChangeMessage(String message){
BaseUpdateMessage newBaseInfo = JSON.parseObject(message, BaseUpdateMessage.class);
dao.upDateBaseInfo(newBaseInfo);
}
and code in APP_A
#Component
public class MessageSender {
#Autowired
private RabbitTemplate rabbitTemplate;
public void editBaseInfo(BaseUpdateMessage message)throws Exception {
//and i am not sure set RemoteInvocationAwareMessageConverterAdapter in this way is right
rabbitTemplate.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());
rabbitTemplate.convertAndSend("MRO_Exchange", "baseInfoUpdate", JSON.toJSONString(message));
}
}
i am very confuse with three points:
1)do i have to use errorHandler and returnExceptions at the same time? i thought errorHandler is something like a postprocessor that let me custom exception.if i don't need a custom exception can i just set returnExceptions with out errorHandler ?
2)should the method annotated with #RabbitListener return something or void is just fine?
3)in the sender side(my situation is APP_A), does have any specific config to catch the exception?
my workspace environment:
Spring boot 2.1.0
rabbitMQ server 3.7.8 on docker
1) No, you don't need en error handler, unless you want to enhance the exception.
2) If the method returns void; the sender will end up waiting for timeout for a reply that will never arrive, just in case an exception might be thrown; that is probably not a good use of resources. It's better to always send a reply, to free up the publisher side.
3) Just the RemoteInvocationAwareMessageConverterAdapter.
Here's an example:
#SpringBootApplication
public class So53846303Application {
public static void main(String[] args) {
SpringApplication.run(So53846303Application.class, args);
}
#RabbitListener(queues = "foo", returnExceptions = "true")
public String listen(String in) {
throw new RuntimeException("foo");
}
#Bean
public ApplicationRunner runner(RabbitTemplate template) {
template.setMessageConverter(new RemoteInvocationAwareMessageConverterAdapter());
return args -> {
try {
template.convertSendAndReceive("foo", "bar");
}
catch (Exception e) {
e.printStackTrace();
}
};
}
}
and
org.springframework.amqp.AmqpRemoteException: java.lang.RuntimeException: foo
at org.springframework.amqp.support.converter.RemoteInvocationAwareMessageConverterAdapter.fromMessage(RemoteInvocationAwareMessageConverterAdapter.java:74)
at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1500)
at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1433)
at org.springframework.amqp.rabbit.core.RabbitTemplate.convertSendAndReceive(RabbitTemplate.java:1425)
at com.example.So53846303Application.lambda$0(So53846303Application.java:28)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:794)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:324)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at com.example.So53846303Application.main(So53846303Application.java:15)
Caused by: java.lang.RuntimeException: foo
at com.example.So53846303Application.listen(So53846303Application.java:20)
As you can see, there is a local org.springframework.amqp.AmqpRemoteException with the cause being the actual exception thrown on the remote server.

Exception in step at specflow

I'm calling in a function to step (specflow),
Then(step's string)
and in step I throw an exception. I want to catch the exception with a different function and not in the step itself. Do someone know how to do it?
Thanks
This is not possible with SpecFlow.
SpecFlow interprets an exception in an step as error and stops the execution of the Scenario.
What you can do, is to catch the exception in your step and save it in a field of the binding class. Then in the second step you can check this field.
like this:
[Binding]
public class BindingClass
{
private Exception _exception;
[When("an exception is thrown")
public void ExceptionThrown()
{
try {
.... //your code that throws an exception
}
catch(Exception e)
{
_exception = e;
}
}
[Then("the exception has the message '(.*)'")]
public void ExceptionHasTheMessage(string message)
{
if (_exception != null)
{
Assert.Equal(_exception.Message, message);
}
}
}
I use the AfterStep hook available in SpecFlow.
The code looks like this:
[AfterStep]
public void AfterStep()
{
if(_scenarioContext.ScenarioExecutionStatus.ToString().Equals("TestError"))
{
Logger.LogScreenshot(exception, _scenarioContext.ScenarioInfo.Title);
}
}
This piece of code will catch your exception and remaining steps will be skipped.

Stopping Fitnesse (Slim) on any exception

We've found the "Fail Fast" principle crucial for improving maintainability of our large Fitnesse-based battery of tests. Slim's StopTestException is our saviour.
However, it's very cumbersome and counterproductive to catch and convert any possible exception to those custom StopExceptions. And this approach doesn't work outside of fixtures. Is there a way to tell fitnesse (preferably using Slim test system) to stop test on any error / exception?
Update: corresponding feature request https://github.com/unclebob/fitnesse/issues/935
Most of the exceptions coming from fixtures are possible to conveniently convert to the StopTestException by implementing the FixtureInteraction interface, e.g.:
public class StopOnException extends DefaultInteraction {
#Override
public Object newInstance(Constructor<?> constructor, Object... initargs) throws InvocationTargetException, InstantiationException, IllegalAccessException {
try {
return super.newInstance(constructor, initargs);
} catch (Throwable e) {
throw new StopTestException("Instantiation failed", e);
}
}
#Override
public Object methodInvoke(Method method, Object instance, Object... convertedArgs) throws InvocationTargetException, IllegalAccessException {
try {
return super.methodInvoke(method, instance, convertedArgs);
} catch (Throwable e) {
throw new StopTestException(e.getMessage(), e);
}
}
public static class StopTestException extends RuntimeException {
public StopTestException(String s, Throwable e) {
super(s, e);
}
}
}

JavaFX - waiting for task to finish

I have a JavaFX application which instantiates several Task objects.
Currently, my implementation (see below) calls the behavior runFactory() which performs computation under a Task object. Parallel to this, nextFunction() is invoked. Is there a way to have nextFunction() "wait" until the prior Task is complete?
I understand thread.join() waits until the running thread is complete, but with GUIs, there are additional layers of complexity due to the event dispatch thread.
As a matter of fact, adding thread.join() to the end of the code-segment below only ceases UI interaction.
If there are any suggestions how to make nextFunction wait until its prior function, runFactory is complete, I'd be very appreciative.
Thanks,
// High-level class to run the Knuth-Morris-Pratt algorithm.
public class AlignmentFactory {
public void perform() {
KnuthMorrisPrattFactory factory = new KnuthMorrisPrattFactory();
factory.runFactory(); // nextFunction invoked w/out runFactory finishing.
// Code to run once runFactory() is complete.
nextFunction() // also invokes a Task.
...
}
}
// Implementation of Knuth-Morris-Pratt given a list of words and a sub-string.
public class KnuthMorrisPratt {
public void runFactory() throws InterruptedException {
Thread thread = null;
Task<Void> task = new Task<Void>() {
#Override public Void call() throws InterruptedException {
for (InputSequence seq: getSequences) {
KnuthMorrisPratt kmp = new KnuthMorrisPratt(seq, substring);
kmp.align();
}
return null;
}
};
thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
When using Tasks you need to use setOnSucceeded and possibly setOnFailed to create a logic flow in your program, I propose that you also make runFactory() return the task rather than running it:
// Implementation of Knuth-Morris-Pratt given a list of words and a sub-string.
public class KnuthMorrisPratt {
public Task<Void> runFactory() throws InterruptedException {
return new Task<Void>() {
#Override public Void call() throws InterruptedException {
for (InputSequence seq: getSequences) {
KnuthMorrisPratt kmp = new KnuthMorrisPratt(seq, substring);
kmp.align();
}
return null;
}
};
}
// High-level class to run the Knuth-Morris-Pratt algorithm.
public class AlignmentFactory {
public void perform() {
KnuthMorrisPrattFactory factory = new KnuthMorrisPrattFactory();
Task<Void> runFactoryTask = factory.runFactory();
runFactoryTask.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t)
{
// Code to run once runFactory() is completed **successfully**
nextFunction() // also invokes a Task.
}
});
runFactoryTask.setOnFailed(new EventHandler<WorkerStateEvent>() {
#Override
public void handle(WorkerStateEvent t)
{
// Code to run once runFactory() **fails**
}
});
new Thread(runFactoryTask).start();
}
}

Resources