What would be the correct way to verify that one behaviour is triggered when there is an argument being passed, and another behaviour is triggered when there are no arguments being passed when running a java app from cmd?
Since the main method is static it's a little tricky to verify, but I also feel that introducing PowerMock is a bit over the top just for that.
Basically I want to create an object with a constructor with no arguments if there are no cmd arguments, and create an object with a String argument constructor if there are passed arguments to the app.
I do not see your code, so I can only imagine how it looks like.
I can imagine that within the main method some logic is triggered, which results in one or another event.
I suggest thinking about moving the processing of the arguments to another class (ArgumentProcessor) which can be fed with a builder object or factory object in the constructor and it could have a process(String [] args) method that returns a runnable or whatever you want to achieve.
If you then feed the ArgumentProcessor with a stubbed builder/factory than I think it should be possible to check if the logic has been processed in the right way.
Related
Going through the Command design pattern I understand that we need to create a Command by setting the context via constructor and then calling the execute method to perform some action on the context. Example:
public class Command implements ICommand {
Device device;
public Command(Device device) {
this.device = device;
}
public void execute() {
this.device.turnOn()
}
}
I was wondering that with this approach we will be required to create a new Command object for every device object we create. Will it be ok to pass the context and some parameters to the execute method? I am looking for something like:
public class Command implements ICommand {
public void execute(Device device) {
this.device.turnOn();
}
}
Are there any issues with this approach?
The idea behind the Command pattern is that it should encapsulate all the information needed to perform an action. This lets you do things like delay the execution of the action until a later time, or even undo the action after it has been executed.
For a concrete example, consider the "Undo" feature in a word processor.
Each time you type in the document, the application uses the Command pattern to record the action.
If you hit "Undo", the text you typed disappears.
Then, when you hit "Redo", the typed text reappears, without the application needing to ask for the input again. It does this by replaying the command that it stored in step 1, which contains all the information about the text you typed.
If your command object requires additional parameters in order to perform the action, it doesn't really implement the Command pattern. It loses most of the advantages of the Command pattern, because the caller can't execute the action without additional information. In your example, the caller would need to know which device is being turned on.
However, that doesn't mean that you have to stick rigidly to the pattern. If it's more useful in your case for the execute method to accept a Device parameter, that's what you should do! If you do that, you should consider renaming the interface, though. Referring to it as a Command pattern when it doesn't follow the pattern exactly could confuse other readers of the code.
When deciding whether to take an object in as a method parameter or a constructor parameter, one of the things I find most helpful is to consider how I'm going to test the application. Objects that form part of the initial setup of the test get passed in as constructor parameters, while objects that form the inputs of the test, or the test vector, are method parameters. I find that following that guideline helps to produce maintainable code.
I want to run MapReduceIndexerTool from Java.
Right now I do it from command line using hadoop jar as you can see here, but I want to check it's status (to see if it's finalized, in progress, etc.) from Java code.
So basically I want to run it from Java in order to be able to check it's status from Java. Is there a way to run it from command line and check it's status from Java?
Also, there is a way to make Map Reduce to send an event (on a callback for example) when a job is completed? Something like a webhook?
As far as I know Tool interface exposes only int run(String[] args) method, so in general you would create new instance, form proper argument string and call that method.
From other hand, MapReduceIndexerTool has int run(Options options) method, that could be used to run it without forming shell-style argument. However, this method is protected, so this will need to have calling class to be created in same package as MapReduceIndexerTool.
I have a method that should only be called once during an object's lifetime. In order to ensure that this is the case, the method sets a boolean flag in the Object to true so it can later check if this method has already run. I am currently throwing an IllegalArgumentException (with a descriptive message) if this method is called a second time during a single object's lifetime, but that doesn't feel quite right to me, since the problem is not actually with the arguments themselves. Is there a better exception to use than an IllegalArgumentException?
I chose not to use an assert statement in this case, because the class and method are both visible outside the package, so the problem may be caused by code outside of my package. Is that correct thinking?
Throw an IllegalStateException.
But since exceptions shouldn't be part of the ordinary control flow, you should add a companion method, which returns a boolean that indicates whether the next call to the method will be successful.
An example for such a companion method is Iterator#hasNext().
A well-designed API must not force its clients to use exceptions for
ordinary control flow. A class with a “state-dependent” method that
can be invoked only under certain unpredictable conditions should
generally have a separate “state-testing” method indicating whether it
is appropriate to invoke the state-dependent method. For example, the
Iterator interface has the state-dependent method next and the
corresponding state-testing method hasNext.1
1: from Effective Java, Chapter 9: Exceptions
What should worry you more than the specific exception type is the fact that you created a bad design here.
Good interfaces make it easy to do the right thing and hard to do the wrong thing.
Meaning: your current implementation makes it easy to call that method twice; respectively you now force your clients to always check if that method was already called.
So, instead of spending your time on the exception type: step back and figure how to dissect your one class into two classes for example. And find a nice so that calling that specific method gives you a different object to work on. Or check if you should rather use a state machine to solve this problem.
I have a static void method from a different class that is invoked along my code as some sort of logger. In order to automatically test the different use cases of my code I was thinking of checking the logs of the system created by such method.
What I thought is to mock that class and overwrite the behaviour of the method so that it outputs to System.err. Also, redirecting System.err as explained here so that I can easily verify the correct functioning of the code.
I do not know how to override the standard behaviour of the method so that it does something (printing to the stderr) instead of what it normally does (by not mocking it) or nothing (what I get my using when(...).thenReturn(...))
Mocking static method is not a good way to go, believe me.
Altough it is possible with for example PowerMock framework (it is going to replace class loader under the hood), but still it is discouraged.
In eclipse, how would I go about making a method call without writing a test class. For example, if I'm making a method that performs a certain algorithm, is it possible for me to simply call the method and pass the parameters in? I know the BlueJ IDE can do this so I'm sure Eclipse can, I'm just not sure how.
Thanks!
You need a main(String[] args) method to run anything in Java, and it needs to be in a class. Solution: create your test class. Welcome to real Java.