This question already has an answer here:
-
Mocking methods of local scope objects with Mockito
5 answers
In this situation?
class A {
public void f() {
B b = new B();
C c = new C();
// use b and c, and how to modify their behaviour?
}
}
How can I fullfill my idea with PowerMock
and EasyMock
?
I don't want to change my compact code for test reasons.
You can do this, see the answer by Matt Lachman. That approach isn't recommended however. It's a bit hacky.
The best approach would be to delegate creation of your dependant objects to a factory pattern and inject the factories into your A
class:
class BFactory {
public B newInstance() {
return new B();
}
}
class CFactory {
public C newInstance() {
return new C();
}
}
class A {
private final BFactory bFactory;
private final CFactory cFactory;
public A(final BFactory bFactory, final CFactory cFactory) {
this.bFactory = bFactory;
this.cFactory = cFactory;
}
public void f() {
B b = bFactory.newInstance();
C c = cFactory.newInstance();
}
}
You would then mock the factories to return mock instances of the dependent classes.
If for some reason this is not viable then your can create factory methods in the A
class
class A {
public void f() {
B b = newB();
C c = newC();
}
protected B newB() {
return new B();
}
protected C newC() {
return newC();
}
}
Then you can use a spy
that mocks those factory methods.
You can, in fact, mock object construction using PowerMock. They have great documentation for it right here: https://code.google.com/p/powermock/wiki/MockConstructor
Also take a look at this example which walks through mocking object construction.
Whitout changing the code it will not work. (Design for testability).
You can replace B with a factory method, that creates B1 in real, or BTest in test, both implementing IB Interface.
Looks like you need Dependency Injection.
You are creating concrete instances of B and C, then you cannot modify the behavior.
Pass the instances as an argument to f(InterfaceB b, InterfaceC c)
, you should make use of polymorphism and then you can pass a mock instance whose behavior you need to change as an argument to this method. So the method does not need to care which type of concrete instance it being passed to it and you can achieve what you need.
I know the names of interfaces are illogical but that could explain the context easily.