Test an overridden method of an inner class with JUnit and Mockito - java

I have a method in a class I need to test. The method uses an external class that I need to mock, so the external class doesn't get tested or executes its dependencies. The special challenge is: one method of the external class gets overridden. Method looks like this:
public void fetchLocalData(final String source, final ObservableEmitter<String> destination) {
final List<String> options = Arrays.asList("recursive","allFiles","includeDir");
// This class comes from a package
final DirScan dirscan = new DirScan(source, options) {
#Override
protected Action getResult(final String result) {
destination.onNext(result);
return Action.Continue;
}
};
dirscan.scan();
destination.onComplete();
}
I tried:
DirScan scanner = mock(DirScan.class);
when(scanner.scan()).thenReturn("one").thenReturn("two");
That didn't work. What do I miss? How would I need to refactor to make this testable?

If you want to replace the dirscan with a mock (or a spy) you'll need to refactor your class that it's a dependency or parameter. Alternatively you could use PowerMockito's whenNew functionality.
Lets assume you change your class and instead of the String source you provide the DirScan object as a parameter. You would need to have some kind of creation method for dirscan elsewhere (might be a static method).
final List<String> options = Arrays.asList("recursive","allFiles","includeDir");
public DirScan createDirScan(String source) {
// This class comes from a package
final DirScan dirscan = new DirScan(source, options) {
#Override
protected Action getResult(final String result) {
destination.onNext(result);
return Action.Continue;
}
};
return dirscan;
}
public void fetchLocalData(final DirScan dirscan, final ObservableEmitter<String> destination) {
dirscan.scan();
destination.onComplete();
}
Juding from your question you seem to want to test the interaction with the destination object, so you do not want to mock the dirscan object (because if you do there won't be any interaction). You might want to use a spy and only replace the getResult method.
In your test now you could then simply pass a spy for the dirscan object and
define the behaviour of it with thenAnswer.
final ObservableEmitter<String> destination = ...
DirScan dirscan = Mockito.spy(createDirScan(source, destination));
Mockito.when(dirscan.getResult(Mockito.any(String.class))).thenAnswer((Answer<Action>) invocation -> {
String result = invocation.getArgument(0);
destination.onNext(result);
return Action.Continue;
});
classUnderTest.fetchLocalData(dirscan, destination);
At this point you might notice that its probably better to not use a spy and just use the real DirScan object. Using the spy to do what you intend to do with the overriden method looks like overkill to me.
The real object has to work for this test to be of value, so you might as well test the real thing.

Related

How to pass a method as an argument to a different method?

I have a method let's say in ClassA. I want to pass a method from ClassB as an argument to that method in ClassA. In this case I want to pass the getCode method from ClassB. I don't have any instance of ClassB and I'd like to achieve this without having to create one.
I've tried using simple method reference, but it does not work this way.
I don't want to make getCode a static method either.
public class ClassA {
public void validate() {
Validation validation = new Validation(ClassB::getCode, code);
//...
}
}
My final goal is to have a RequestValidator class to which add validations, each validation will be created with a specific method and a string in its constructor, in this case getCode from classB and code. Please note I only want one instance of RequestValidator. Something like this:
RequestValidator validator = new RequestValidator<>()
.addValidation(new Validation(ClassB::getCode, code))
.addValidation(new Validation(ClassB::getName, name));
getCode needs to be a static function, and the syntax would be ClassB.getCode. You would need ClassB to be imported into ClassA.
See:
Calling static method from another java class
Your use of a method reference will work just fine as long as you define the method arguments properly. You haven't given a lot of information, so I'm going to make some assumptions here. Please correct me if this isn't what you had in mind:
public class B {
public static String getCode() {
return "foobar"; // Replace with your own functionality
}
}
public class Validation {
Validation(Supplier<String> supplier, String code) {
String suppliedCode = supplier.get();
// Do your validation logic
}
}
public static void validate() {
Validation validation = new Validation(ClassB::getCode, code);
}
But this frankly feels like overkill. Why can't you just make your Validation constructor take two String arguments (or whatever types you happen to be using), and then do this?
public static void validate() {
Validation validation = new Validation(ClassB.getCode(), code);
}
Do you have a legitimate need to pass in a method reference instead of simply passing in the return value from the method call?

How to test a toString() method?

If I have something like this:
public class Set {
private ArrayList<String> testList;
private String testString;
public Set() {
}
public void add(String testString) {
testList.add(testString);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(testString).append(System.getProperty("line.separator"));
return sb.toString();
}
}
How can I test this in a main method?
This is what I've tried so far...
Set test = new Set();
test.add("blah");
test.add("blahhh");
System.out.println(blah.toString());
Am I doing this correctly? Taking my first CS course in High School and we're supposed to make a class that implements a toString() method.
you creacted the object test of the class Set just write now just:
System.out.println(test);
will give you the result you want since it will use the toString method
and your testString is not set so the toString will return null
You can test your toString this way, but for this purpose you should use Unit Tests (see junit).
For testing your Class you should try it with different types of input, to see, what happens, if someone enteres something unexpected.
And you have errors in your Code:
Set test = new Set();
test.add("blah");
test.add("blahhh");
System.out.println(blah.toString());
There is no blah variable:
System.out.println(test.toString());
or just:
System.out.println(test);
For learning purposes you should do something more usefull in your toString. You could try to create a Class bank account with balance, owner data (name, address, ...) and creating in the toString an interesting output.
You are asking about testing; then dont go for print statements.
Turn to a unit test environment, like JUnit; and write real tests:
#Test
public testToStringWithTwoEntries() {
Set underTest = new Set();
underTest.add(...
assertThat(underTest.toString(), is("blah, blahhh"));
}
for example. Notes:
assertThat() is simply one of the most powerful of the various different assert methods; and it is easy to use; one just has to understand that it requires Hamcrest matchers to work (that is where the is() call is coming from)
you named your class "Set" ... bad idea. There is already a well-known interface java.util.Set. You never want to re-use such names.
A very good library for testing toString on model classes: https://github.com/jparams/to-string-verifier
Sample:
#Test
public void myTest()
{
ToStringVerifier.forClass(Set.class).verify();
}

Instantiating an Object using Java Reflection

I am testing a private method using JUnit and I am invoking it using Reflection. The error I am getting is java.lang.InstantiationException. I know it is not creating an instance of Class but I am not sure what I am doing wrong. Object object = clazz.newInstance(); is the line that throws Exception.
Method under test
private int _getType(String type) {
if ("DATE".equalsIgnoreCase(type)) return Types.DATE;
if ("STRING".equalsIgnoreCase(type)) return Types.VARCHAR;
if ("INT".equalsIgnoreCase(type)) return Types.INTEGER;
if ("TIMESTAMP".equalsIgnoreCase(type)) return Types.TIMESTAMP;
return Types.NULL;
}
JUnit test
#Test
public void testGetType() throws Exception {
String type1 = "DATE";
String type2 = "STRING";
String type3 = "INT";
String type4 = "TIMESTAMP";
Class clazz = SpringStoredProcImpl.class;
Object object = clazz.newInstance();
Method method = object.getClass().getDeclaredMethod("getType", String.class);
method.setAccessible(true);
method.invoke(object, type1);
I don't have my asserts yet so please ignore it.
Thanks in advance.
You try to create an instance with a no argument constructor which does exist in your case.
As the constructors are public you should first create your object normally using the new keyword, then execute the rest of your code starting from Method method...
FYI, if you wanted to create your object by reflection it would be something like clazz.getConstructor(DataSource.class, String.class, ArrayList.class).newInstance(dataSource, sprocName, params) instead of simply clazz.newInstance()
Different answer: don't do that.
Why do you think you need to make this method private? It looks like the responsibility of this method is to "lookup" an enum type, based on string input. I think it would make much more sense to simply make this method package protected and avoid the reflection overhead/hassle.

How to Avoid Constructor calling During Object Creation?

I want to avoid the constructor calling during object creation in java (either default constructor or user defined constructor) . Is it possible to avoid constructor calling during object creation???
Thanks in advance......
Simply extract the intialization logic that you want to avoid into another method called init. You can not avoid calling exactly one constructor.
No matter what pattern or strategy you use, at some point your will need to call a constructor if you want to create an object.
Actually, its possible under some circumstances by using classes from the JVM implementation (which do not belong to the JRE API and are implemenation specific).
One example here http://www.javaspecialists.eu/archive/Issue175.html
It should also be possible using sun.misc.Unsafe.allocateInstance() (Java7)
Also, the constructor is apparently bypassed when using the clone()-method to create a copy of an object (and the class doesn't override clone to implement it different from the Object.clone() method).
All of these possibilities come with strings attached and should be used carefully, if at all.
You can mock the constructors of a class. They will still be called, but not executed. For example, the following JUnit+JMockit test does that:
static class CodeUnderTest
{
private final SomeDependency someDep = new SomeDependency(123, "abc");
int doSomething(String s)
{
someDep.doSomethingElse(s);
return someDep.getValue();
}
}
static final class SomeDependency
{
SomeDependency(int i, String s) { throw new RuntimeException("won't run"); }
int getValue() { return -1; }
}
#Test
public void mockEntireClassIncludingItsConstructors()
{
new NonStrictExpectations() {
#Mocked SomeDependency mockDep;
{ mockDep.getValue(); result = 123; }
};
int result = new CodeUnderTest().doSomething("testing");
assertEquals(123, result);
}

Junit, Mockito, how to test a callbacks [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Intercept object on method invocation with Mockito
I have an class that can mapp from one format to another. Since this is legacy code I don't dare to rewrite it, it is basically a set of plugins so if I change one I might have to change all the other. It wasn't developed with testing in mind.
So this is my problem.
interface Mapper {
void handle(ClassA classA);
void handle(ClassB classB);
}
public interface Publisher {
public void publish(MappedClass mappedClass);
}
class MyMapper implements Mapper {
private Publisher publisher;
public void setPublisher(final Publisher publisher) {
this.publisher = publisher;
}
public handle(ClassA classA) {
final MappedClass mappedClass = // Map from ClassA to MappedClass
publisher.publish(mappedClass);
}
public handle(ClassB classB) {
final MappedClass mappedClass = // Map from ClassB to MappedClass
publisher.publish(mappedClass);
}
}
Okay. So depending on which class was "handled" MappedClass will be published with different values, and it is the values I want to verify (test). The problem is that I will get a test where I first have to write code that tests that the publish method is called,
private boolean wasCalled;
#Test
public void testClassAMapped() {
wasCalled = false;
final MyMapper myMapper = new MyMapper();
myMapper.setPublisher(new Publisher() {
public void publish(final MappedClass mappedClass) {
wasCalled = true;
// Code for verifying the fields in mappedClass
});
}
final ClassA classA = // Create classA
myMapper.handle(classA);
assertTrue(wasCalled);
}
So first we create our mock Publisher which will first set the state of wasCalled to true so we know this method was ever called (this example is simplified so there is actually a dispatcher in the code... legacy code so I don't want to change it), second I want to verify that MappedClass has the correct field values.
What I would like to know is if anyone knows a better way to test this? The wasCalled, and wasCalled check becomes more or less boilerplate code for many of my tests, but since I don't want to add that much clutter (own hacks, test base classes, etc) I would like to know if there is a way to do this in Mockito, or EasyMock?
Use an Mockito ArgumentCaptor
#Test
public void test(){
Publisher publisher = Mockito.mock(Publisher.class);
myMapper.setPublisher(publisher);
ArgumentCaptor<MappedClass> captor = ArgumentCaptor.forClass(MappedClass.class);
....
myMapper.handle(...);
...
verify(publisher).publish(captor.capture());
MappedClass passedValue = captor.getValue();
// assert stuff here
}
I'm not sure I fully understand the problem, but it looks like you are looking for Mockito.verify(publisher).publish(Matchers.isA(MappedClass.class));
For that to work, you'd have to mock the Publisher through
Publisher publisher = Mockito.mock(Publisher.class)
and then hand that into MyMapper.
If you need to assert the state of the MappedClass, use an ArgumentCaptor. See this answer for an example.
The Mockito-API-doc has many additional examples.

Categories

Resources