I have the following class:
public class MyClass {
private Apple apple;
public void myMethod() {
apple = AppleFactory.createInstance(someStringVariable);
....
....
....
}
}
And the Test class:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#InjectMocks
MyClass myClass;
#Test
public void myMethod(){
...
...
...
}
}
How could I inject an Apple instance as a mock in MyClass?
You have 3 possibilities to solve this:
Abstract factory: Instead of using a static method, use a concrete factory class:
public abstract class AppleFactory {
public Apple createInstance(final String str);
}
public class AppleFactoryImpl implements AppleFactory {
public Apple createInstance(final String str) { // Implementation }
}
In your test class, mock the factory:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private AppleFactory appleFactoryMock;
#Mock
private Apple appleMock;
#InjectMocks
MyClass myClass;
#Before
public void setup() {
when(appleFactoryMock.createInstance(Matchers.anyString()).thenReturn(appleMock);
}
#Test
public void myMethod(){
...
...
...
}
}
PowerMock: Use PowerMock to create a mock of a static method. Look at my answer to a relevant question to see how it's done.
Testable class: Make the Apple creation wrapped in a protected method and create a test class that overrides it:
public class MyClass {
private Apple apple;
public void myMethod() {
apple = createApple();
....
....
....
}
protected Apple createApple() {
return AppleFactory.createInstance(someStringVariable);
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private Apple appleMock;
#InjectMocks
MyClass myClass;
#Test
public void myMethod(){
...
...
...
}
private class TestableMyClass extends MyClass {
#Override
public void createApple() {
return appleMock;
}
}
}
Of course, in your test class you should test TestableMyClass and not MyClass.
I'll tell you my opinion on each of the methods:
The abstract factory method is the best one - This is a clear design that hides the implementation details
The testable class - Is the second option which requires minimum changes
The PowerMock option is my least favorite - Instead of going for a better design, you ignore and hide your problem. But that's still a valid option.
In addition of the solution proposed by Avi, you can choose a fourth possibility:
Inject into Factory:
This is, for me, the best option when you already have code to refacrot. With this solution you don't have to change porduction code but only factory class and test.
public class AppleFactory
{
private static Apple _injectedApple;
public static createInstance(String str)
{
if (_injectedApple != null)
{
var currentApple = _injectedApple;
_injectedApple = null;
return currentApple;
}
//standard implementation
}
public static setInjectedApple(Apple apple)
{
_injectedApple = apple;
}
}
Now you can use your static factory simply:
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock
private Apple appleMock;
#InjectMocks
MyClass myClass;
#Before
public void setup() {
AppleFactory.setInjectedApple(appleMock);
}
#Test
public void myMethod(){
...
...
...
}
}
Related
I want to test a method which creates an object of another class using it's parameterized constructor. Even though I've mocked the constructor of MyClass, it makes the third party library which is in constructor implementation and results in the error. I'm using Mockito/PowerMockito.
public class MyClass{
private MyObj obj;
MyClass (String profile)
{
//some 3rd party library call
obj = thridPartyLib.someMethod(profile);
}
public String someMethod(){
return obj.someExternalCall();
}
}
Class which I want to test
public class ClassTobeTested{
public void execute(){
//some code
// ......
MyClass myClass = new MyClass(profile);
myclass.someMethod();
}
}
What I tried so far - classUnderTest.execute() ends up calling the thridPartyLib.someMethod(profile); which is part of MyClass constructor.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = new ClassTobeTested();
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute(){
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
Your code will work only if you are working with a spy or mock of classUnderTest. Try this. This should work
#RunWith(PowerMockRunner.class)
#PrepareForTest( {MyClass.class, ClassTobeTested.class })
public class ClassTobeTestedTest {
private MyClass mockMyClass;
private ClassTobeTested classUnderTest;
#Before
public void init() {
classUnderTest = spy(new ClassTobeTested());
mockMyClass = PowerMockito.mock(MyClass.class);
}
#Test
public void testExecute() throws Exception {
PowerMockito.whenNew(MyClass.class)
.withArguments(Mockito.any())
.thenReturn(mockMyClass);
classUnderTest.execute();
}
}
The pain might suggest another approach. Consider injecting a Factory into ClassTobeTested which knows how to create an instance of MyObj. For example:
class MyObjFactory {
MyObj create(String profile) {
return new MyClass(profile);
}
}
then
public class ClassTobeTested {
private final MyObjFactory factory;
public ClassTobeTested(MyObjFactory factory) {
this.factory = factory;
}
public void execute(){
//some code
// ......
// MyClass myClass = new MyClass(profile);
MyClass myClass = factory.create(profile);
myclass.someMethod();
}
}
so the unit test becomes simpler with only having to mock the Factory and have it return a mocked MyClass instance. Then it's simple to verify myclass.someMethod() was invoked as expected.
How to test a class which depends on Provider<>?
Please see the code below.
class ToTest {
#Inject
Provider<Processor> processorProvider;
public buildData() {
processorProvider.get().process();
}
class ProcessorProviderImpl implements Provider<Processor> {
#Inject
private Handler someHandler;
public Processor get() {
return new MyProcessor(somehandler)
}
}
public static class TestModule extends JukitoModule {
#Override
protected void configureTest() {
bind(Processor.class).toProvider(
ProcessorInstanceProviderImpl.class);
bindMock(SubHandler.class).in(TestSingleton.class);
}
}
class Handler {
#Inject
private SubHandler subHandler; // this is singleton instance
}
}
So when I mock subHandler it doesn't work and when I run unit test I am getting a NullPointerException where subHandler.handle() is getting called.
You can use Providers.of() to initialize processorProvider with a provider of your collaborator instance.
https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/util/Providers.html
test = new ToTest();
test.processorProvider = Providers.of(processorMock);
I am newbie in Java world, but it is very hard understand why not can I stub method of a mocked object...
#RunWith(MockitoJUnitRunner.class)
public class ChildBLLIT extends BaseInteractorIT {
#InjectMocks
private ChildBLL ChildBLL = Mockito.mock(ChildBLL.class);
#Before
public void setUp() {
ChildBLL.engine = engineMock;
}
/**
* Test of getZipStatistics method, of class ChildBLL.
*/
#Test
public void testGetZipStatistics() {
final String testZipStatisticsText = "DummyZipStatistics";
//This method will throw the null pointer exception
when(ChildBLL.engine.getZIPStatistics()).thenReturn(testZipStatisticsText);
ChildBLL.getZipStatistics();
verify(ChildBLL.engine).getZIPStatistics();
}
}
When I try to stub the getZIPStatistics() method I get always a null pointer exception, of course I get, because in the getZIPStatistics() method there is an private object, which is not mocked... it seems to me the Mockito does not mocking the private fields... and unfortunately this is from another project:
public class BaseIT {
#Mock
protected static FromOtherProject engineMock;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
}
Here I mocked the engine variable, but then how can I mock/stub the getZIPStatistics() method? This is this method:
public class FromOtherProject {
//...
public final String getZIPStatistics() {
return ZIPStatistics.toString();
}
}
What can I do?
Let's assume a simple class...
public class Account {
public String getPassword() {
return "abc";
}
}
...and simple class that contains it...
public class AccountHolder {
private Account account;
public String getAccountPassword() {
return this.account.getPassword();
}
}
So now we have a simple base class for all Account based tests...
public class AccountBasedTest {
#Mock
protected Account account;
}
...and a class that actually tests the AccountHolder...
#RunWith(MockitoJUnitRunner.class)
public class AccountHolderTest extends AccountBasedTest {
#InjectMocks
private AccountHolder accountHolder;
#Test
public void getAccountPasswort_must_return_account_password() {
Mockito.when( this.account.getPassword() ).thenReturn ("xyz");
Assert.assertEquals("xyz", this.accountHolder.getAccountPassword());
}
}
And that's all. The #InjectMocks, etc. annotations will also look in the superclasses, so you get your mocked account and that account will be put into your AccountHolder. No need to call MockitoAnnotations.initMocks. It shouldn't hurt, but it's not needed because you are using the MockitoJUnitRunner already, which does exactly that.
For example I have the following handler:
#Component
public class MyHandler {
#AutoWired
private MyDependency myDependency;
public void someMethod(Object parameter) {
...
ThirdPartyClass thirdPartyObject = new ThirdPartyClass(parameter);
thirdPartyObject.unnecessaryMethod();
...
}
}
To test this, I want to write something like this:
#RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {
#InjectMocks
MyHandler myHandler;
#Mock
MyDependency myDependency;
#Test
public void testSomeMethod() {
...
myHandler.someMethor(parameter);
...
}
}
I want to avoid calling unnecessaryMethod(). Is there any way to do this?
If unnecessaryMethod() is static then I can use PowerMockito to mock it, but can PowerMockito help in my situation?
I have found an answer:
public class MyHandler {
public void someMethod() {
Utils utils = new Utils(10);
System.out.println("Should be 1 : " + utils.someMethod());
}
}
Some Utils class:
public class Utils {
private int value = 5;
Utils () {
System.out.println("Should be mocked");
}
Utils (int param) {
this.value = param;
System.out.println("Should be mocked");
}
public int someMethod() {
System.out.println("Should be mocked");
return value;
}
}
And test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyHandler.class)
public class MyHandlerTest {
#InjectMocks
MyHandler myHandler;
#Test
public void testMain() throws Exception {
Utils utils = mock(Utils.class);
when(utils.someMethod()).thenReturn(1);
whenNew(Utils.class).withArguments(anyInt()).thenReturn(utils);
myHandler.someMethod();
}
}
Console output will be:
Should be 1 : 1
Related question
When class hierarchy is not linear, aspect is not triggered when defined on base interface.
The most interesting: when adding delegating implementation (see last code block) to the parent class of the implementation, the test becomes Green (Aspect is triggered as expected).
Question: Why doesn't it work as described in example and why does it work with delegating implementation?
Example (sorry, no shorter example found):
Test:
#Autowired
private TheInterface underTest;
private static boolean aspectCalled;
private static boolean implementationCalled;
#Test
public void aspectTest() throws Exception {
aspectCalled = false;
implementationCalled = false;
underTest.doSomething();
assertTrue("Implementation not called!", implementationCalled);
assertTrue("Aspect not called!", aspectCalled);
}
Aspect:
#Aspect
#Component
public static class MyAspect {
#Before("execution(* *..SpecializedInterface+.doSomething())")
public void applyAspect() {
aspectCalled = true;
}
}
Interfaces:
public static interface TheInterface {
void doSomething();
}
public static interface SpecializedInterface extends TheInterface {
// inherits doSomething
// defines some other methods
}
Abstract implementations (Template pattern):
public static abstract class BaseTemplate implements TheInterface {
abstract void doOneStep();
#Override
public void doSomething() {
// do some stuff and
doOneStep();
}
}
public static abstract class SpecializedTemplate extends BaseTemplate implements SpecializedInterface {
// some other methods
}
Implementing bean:
#Component
public static class TemplateImplementation extends SpecializedTemplate {
#Override
void doOneStep() {
implementationCalled = true;
}
}
(If you are interested: test setup:)
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = MyConfig.class)
public class AopTest {
#Configuration
#EnableAspectJAutoProxy
#ComponentScan(basePackageClasses = AopTest.class)
public static class MyConfig {
}
...
Ugly workaround: add this snippet to SpecializedTemplate
#Override
public void doSomething() {
super.doSomething();
}
So, why is this workaround necessary?
Thomas Stets has already explained the bytecode and JVM stuff, so I will just provide a solution to your problem, see also my answer to a very similar question.
#Aspect
public static class MyAspect {
#Before("execution(* *..TheInterface+.doSomething()) && target(specializedInterface)")
public void applyAspect(SpecializedInterface specializedInterface) {
aspectCalled = true;
}
}
I.e. your pointcut targets the base interface actually defining the method, then you limit the target to the specialised sub-interface of your choice. This should make your test green.