Mocking subclass object and superclass reference - java

Here is the scenario, I have something like this in one of my method of cls:
public class xyz{
public Object build(Map map) {
BaseClass cls;
if(SomeconditionTrue) {
cls = new ChildClass1(new ABC());
} else {
cls = new ChildClass2(new ABC());
}
cls.callMethod();
}
}
For the above scenario, I am writing a test case using PowerMockito, I want to mock this method call, cls.callMethod(). When i am trying the normal mocking, it calls the actual Method callMethod() that is failing. can some body please help me to mock that method call? Tried using couple of scenarios using PowerMockito.stub and some of other options, but its always calling the actual method.

Using Powermock you could do something like the following:
PowerMockito.whenNew(ChildClass1.class)
.withArguments(any(ABC.class))
.thenReturn(mockedBaseClass);
PowerMockito.whenNew(ChildClass2.class)
.withArguments(any(ABC.class))
.thenReturn(mockedBaseClass);
Of course my preferred approach would be to pass in a factory that knows about how to make these ChildClass instances, then you could mock it using Mockito and it would be cleaner. However if that is not an option, hopefully the above should work.

Related

How to spy on a Method that belongs to an object not accessible from outside?

I'm very new to Mockito and I have a situation for which I can't find a solution. There's a method that I want to test using Mockito. The problem is that inside this method, there's an object created and that object has a function that I want to mock.
So for example, here is a small sample code which illustrates my issue:
public class ClassA {
public functionDoingDBStuff() {
//...........
}
}
public class ClassB {
final ClassA classAObj = null;
public functionXYZ() {
classAObj = new ClassA();
classAObj.functionDoingDBStuff();
}
}
#Test
MyTestFunction() {
ClassB classBObj = new ClassB();
// How can I access and mock functionDoingDBStuff() here?
}
So in MyTestFunction(), I want to test functionXYZ(), but mock the function functionDoingDBStuff() that is called inside functionXYZ(). By mock, I mean return a specific result that I want for the test. However function functionDoingDBStuff() belongs to an object that's created inside functionXYZ(), so I don't know how I can tell Mockito to access it from within MyTestFunction(). I hope you're able to understand what I mean.
To me if a piece of code can't be easily tested that suggests a problem with the structure of the code. Anyway, why does new ClassA() need to be done inside the functionXYZ? Can't be instantiated (better still injected) at Object level? If so you can inject a mock instance of ClassA.
If it still has to be instantiated within the method, may be instead of doing new ClassA(), it should be wrapped inside a factory method. Then you can mock the factory to return a mock ClassA.

How to mock an object created via Class.newInstance(className)?

I'm trying to add unit tests to some legacy code that has a String class name passed to it and that creates an object implementing a particular handler interface using Class.newInstance(String className). I can control the class name I'm passing, I can get a pointer to the new handler object (via a getHandler() call), and I would like to observe calls to it using Mockito.
My current solution is:
Create a new test class TestHandler that implements the interface.
Have that test class contain a Mockito mock object that also implements the interface.
Manually pass through all the interface methods to the mock object.
Make the mock object accessible via a getMock() method.
Observe the object by making verify() calls to objectUnderTest.getHandler().getMock().
This works, but feels a little inelegant, especially having to manually write all the pass-thru methods.
Is there a better solution?
Fundamentally, you're running into the same problems as trying to test a newly-created instance using new; the Class.newInstance (probably properly Class.forName(foo).newInstance()) doesn't hurt you, but doesn't help you either.
As a side note, your TestHandler sounds like a general purpose delegate implementation, which sounds pretty useful anyway (particularly if you ever need to write a Handler wrapper). If it is, you might want to promote it to be adjacent to your Handler in your production code tree.
Though I recognize that you mention legacy code, this becomes very easy if you are allowed to refactor to include a testing seam. (Ignoring reflective exceptions here for ease of explanation.)
public ReturnType yourMethodUnderTest(String className) {
return yourMethodUnderTest(Class.newInstance(className));
}
/** Package private for testing. */
public ReturnType yourMethodUnderTest(Handler handler) {
return yourMethodUnderTest(Class.newInstance(className));
}
You could also extract the object creation and replace it in your test:
/** Instance field, package-private to replace in tests. */
Function<String, Handler> instanceCreator =
( x -> (Handler) Class.forName(x).newInstance());
public ReturnType yourMethodUnderTest(String className) {
Handler handler = instanceCreator.apply(className);
// ...
}
You could even just extract it to a method and replace it in your test:
public ReturnType yourMethodUnderTest(String className) {
Handler handler = createHandler(className);
// ...
}
/** Package private for testing. */
Handler createHandler(String className) {
return Class.forName(className).newInstance();
}
#Test public void yourTest() {
// Manually replace createHandler. You could also use a Mockito spy here.
ObjectUnderTest objectUnderTest = new ObjectUnderTest() {
#Override Handler createHandler(String className) {
return mock(Handler.class);
}
}
// ...
}
Side note: Even though Mockito creates a named dynamic type, you almost certainly will not be able to hack it in and allow your code to create it by name. This is because the call to mock registers the instance within Mockito's internal state.
// BAD: Unlikely to work
#Test public void yourTest() {
objectUnderTest.methodUnderTest(
mock(Handler.class).getClass().getName());
// ...
}
Create a public method where you will place the logic to fetch the newInstance of the class
ClassA objectClassA=createNewInstance(className);
likewise,and
public ClassA createInstance(String className){
return (ClassA) (Class.forName(className)).newInstance();
}
Now suppose we were creating an instance of classA inside of ClassB
then in TestClass of B, we can simply mock this createInstance method
doReturn(mockClassA).when(mockClassB).createInstance(className);

How can I mock a call to a function using mockito in a java junit test

I have a jUnit test which tests one of my functions. In that function I make a call to another class's method which I want to mock using mockito. However, I can't seem to actually mock this. Here is what my jUnit test looks like:
#Test
public void testingSomething() throws Exception {
mock(AuthHelper.class);
when(new AuthHelper().authenticateUser(null)).thenReturn(true);
Boolean response = new MainClassImTesting().test();
assertTrue(response);
}
EDIT: In my MainClassImTesting().test() function that I'm calling, it makes a call to authenticateUser() and passes it a hashMap.
Mockito will allow you create a mock object and have its methods return expected results. So in this case, if you want the authenticateUser method of your mocked AuthHelper instance return true regardless of the value of the HashMap parameter, your code would look something like this:
AuthHelper mockAuthHelper = mock(AuthHelper.class);
when(mockAuthHelper.authenticateUser(any(HashMap.class))).thenReturn(true);
However, your mocked object is useless to your MainClassImTesting unless it has access or reference to it. You can achieve that by adding AuthHelper to the constructor of MainClassImTesting so that the class (including your test method) has access to it.
MainClassImTesting unitUnderTest = new MainClassImTesting(mockAuthHelper);
Boolean response = unitUnderTest.test();
assertTrue(response);
Or if your test method is the only method that needs AuthHelper, you can simply make AuthHelper a method parameter.
MainClassImTesting unitUnderTest = new MainClassImTesting();
Boolean response = unitUnderTest.test(mockAuthHelper);
assertTrue(response);
If you want to mock the function call for any parameter of type A, just do :
AuthHelper authHelper = Mockito.mock(AuthHelper.class);
Mockito.when(authHelper.authenticateUser(any(A.class))).thenReturn(true);

Get method invocated inside a method in Java

I want to make a JUnit test to assure that some classes don't use a specific set of methods (from another classes). Example
class MyClass
{
void myMethod()
{
otherClass.otherClassStaticMethod();
}
}
class myTest
{
void test()
{
assertFalse(CalledMethods.getMethodsCalledBy("myClass.myMethod").Contains("otherClass.otherClassStaticMethod"));
}
}
In this test I want to assure that myMethod doesn't invocate otherClassStaticMethod. How can I find what methods are being called inside a method in compile time (ignore methods called using reflection)? I thought about a .java parser, do you recommend any?
you can mock "otherClass" and verify that the method isn't invoked. E.g. using Mockito you can even specify in which order what methods are supposed to be invoked (under the condition their instances are mocks) and specify which methods are not allowed to be invoked
as coding.mof said, to mock static methods you should use PowerMock/PowerMockito:
example:
PowerMockito.mockStatic(OtherClass.class);
PowerMockito.verifyStatic(never());
OtherClass.otherClassStaticMethod();
It sounds like you should be using a mock library and let that handle it all for you. I'd recommend JMock as my library of choice. If you're using instance methods then this would be perfect for you - if, as your example shows, it's static methods then PowerMock may work*1.
With JMock, you'd have something like:
public class MyClass {
public MyClass(Dependency dependency) {
this.dependency = dependency;
}
void myMethod() {
dependency.someMethod();
}
}
#RunWith(JMock.class)
public class MyTest {
private Mockery context = new Mockery();
#Test
public void doesNotCallSomeMethod() {
Dependency dependency = context.mock(Dependency.class);
MyClass obj = new MyClass(dependency);
obj.myMethod(); <--- this will fail fast
}
}
When you call obj.myMethod, JMock will instantly report that you never said dependency should have any methods called. It will also tell you what method you DID call and what parameters you passed in if any
*1 I don't use PowerMock as I steer away from static methods unless they are pure functions

Can I mock a super class method call?

Sometimes, you want to test a class method and you want to do an expectation on a call of a super class method. I did not found a way to do this expectation in java using easymock or jmock (and I think it is not possible).
There is a (relative) clean solution, to create a delegate with the super class method logic and then set expectations on it, but I don't know why and when use that solution ¿any ideas/examples?
Thanks
Well, you can if you want to. I don't know if you are familiar with JMockit, go check it out. The current version is 0.999.17 In the mean time, let's take a look at it...
Assume the following class hierarchy:
public class Bar {
public void bar() {
System.out.println("Bar#bar()");
}
}
public class Foo extends Bar {
public void bar() {
super.bar();
System.out.println("Foo#bar()");
}
}
Then, using JMockit in your FooTest.java you can validate that you're actually making a call to Bar from Foo.
#MockClass(realClass = Bar.class)
public static class MockBar {
private boolean barCalled = false;
#Mock
public void bar() {
this.barCalled = true;
System.out.println("mocked bar");
}
}
#Test
public void barShouldCallSuperBar() {
MockBar mockBar = new MockBar();
Mockit.setUpMock(Bar.class, mockBar);
Foo foo = new Foo();
foo.bar();
Assert.assertTrue(mockBar.barCalled);
Mockit.tearDownMocks();
}
Expanding on #Cem Catikkas answer, using JMockit 1.22:
#Test
public void barShouldCallSuperBar() {
new MockUp<Bar>() {
#Mock
public void bar() {
barCalled = true;
System.out.println("mocked bar");
}
};
Foo foo = new Foo();
foo.bar();
Assert.assertTrue(mockBar.barCalled);
}
No need for the static class annotated with #MockClass, it is replaced by the MockUp class.
I don't think I'd mock out a super call - it feels to me like the behaviour there is part of the behaviour of the class itself, rather than the behaviour of a dependency. Mocking always feels like it should be to do with dependencies more than anything else.
Do you have a good example of the kind of call you want to mock out? If you want to mock out a call like this, would it be worth considering composition instead of inheritance?
There are several tests that do just that (ie specify an expected invocation on a super-class method) using the JMockit Expectations API, in the Animated Transitions sample test suite. For example, the FadeInTest test case.
No, there is no way of mocking super class methods with jMock.
However there is a quick-and-dirty solution to your problem. Suppose you have class A and class B extends A. You want to mock method A.a() on B. You can introduce class C extends B in your test code and override the method C.a() (just call super, or return null, id does not matter). After that mock C and use the mock everywhere, where you'd use B.
intercepting a super call is much too fine-grained. Don't overdo the isolation.

Categories