Let's say I have classA and classB:
public class A {
private B b;
public A(String id){
this.b = new B(id);
}
public void doSomethingA(String id){
// do somethingA
}
}
public class B{
public B(String id){
// call anotherThing (id)
}
public void doSomethingB(){
//somethingB
}
}
now I want to test methods inside classA (with it's instance) but wanna mock classB
Mockito allows me to mock classB, but when I instantiate classA, the constructor calls classB (which I want to avoid)
Is there a way to mock only the constructor (either classA or classB) but not the other methods?
You may mock any B object but you don't want to.
You want to mock the B b field of the A class.
Which is different.
You have to refactor your design and do B instantiation a dependency and not an internal processing.
A simple way is passing directly the B variable instead of the String as parameter :
public class A {
private B b;
public A(B b){
this.b = b;
}
public void doSomethingA(String id){
// do somethingA
}
}
Now mocking is straight :
#Mock B b;
public void test(){
A a = new A(b);
}
An alternative way would be using a Function<String, B> .
public class A {
private B b;
public A(Function<String, B> bFunction, String id){
this.b = bFunction.apply(id);
}
public void doSomethingA(String id){
// do somethingA
}
}
Mocking becomes so :
#Mock B b;
public void test(){
A a = new A(s-> b, "anyValue");
}
And implementation code could instantiate A as :
A a = new A(B::new, "id");
Related
class A {
int a;
public int add() {
B b = new B();
a = b.calculate(4, 5);
return a;
}
}
class B {
public int calculate(int x, int y) {
return x * y;
}
}
I want to test class A, where and did not want to test the b.calculate() in the add() method.
So I need to mock the class B.
Here is my code.
#Mock
B bclass;
A aclass;
#Before
public void setUp() {
bclass = new B();
aclass = new A();
}
#Test
public void testAClass() {
when(bclass.calculate(4, 5)).thenReturn(45);
assertEquals(45, aclass.add());
}
The test getting failed. What's wrong with it?
It looks like you are using Mockit framework.
You could try doing the following:
new MockUp<B>() {
#Mock
int calculate(int x, int y) // no access modifier required
{
return 45; // your value
}
};
The #Mock annotation already generates the instance of the B. We do not need to create instance again here. Also, make sure you are annotating with Valid Runner or using the Rule.
#RunWith(MockitoJUnitRunner.class)
Let us know the error shown if it is not working. You can also refer the below link on using mockito.
http://www.vogella.com/tutorials/Mockito/article.html#mockito_usage
Your problem is the hidden dependency of class A to class B.
The answer of #Jens showed you how to solve this with PowerMock but I concider this as a surrender to your bad design.
The better was is to make this dependency explicit by injecting an instance of class B into objects of class A preferably as Constructor parameters.
Preferably using a dependency injection framework like guice or spring.
the you can use regulat Mockito constructs.
class A {
int a;
private final B b;
public A(B b){
this.b=b;
}
public int add() {
a = b.calculate(4, 5);
return a;
}
}
#Mock
B bclass;
A aclass;
#Before
public void setUp() {
aclass = new A(bclass);
}
#Test
public void testAClass() {
when(bclass.calculate(4, 5)).thenReturn(45);
assertEquals(45, aclass.add());
}
I am not sure if it is possible with Mockito. With PowerMockito it works:
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class BTest {
A aclass;
B bMock;
#Before
public void setUp() throws Exception {
bMock = PowerMockito.mock(B.class);
PowerMockito.whenNew(B.class).withNoArguments().thenReturn(bMock);
aclass = new A();
}
#Test
public void testAClass() {
Mockito.when(bMock.calculate(4, 5)).thenReturn(45);
Assert.assertEquals(45, aclass.add());
}
}
Let's say I have Following classes:
public class A {
#Autowired B b;
public void doSomething(){
b.doSomeThingElse();
}
#Component
#Autowired C c;
public class B {
public void doSomethingElse(){
c.doIt();
}
How can I test A when you know I want to mock c.doIt() but want to call b.doSomethingElse(); with EasyMock?
Thanks in advance
#Autowired is nice but tend to make us forget about how to test. Just add a setter for b and c.
C c = mock(C.class);
c.doIt();
replay(c);
B b = new B();
b.setC(c);
A a = new A();
a.setB(b);
a.doSomething();
verify(c);
Or use constructor injection.
C c = mock(C.class);
c.doIt();
replay(c);
B b = new B(c);
A a = new A(b);
a.doSomething();
verify(c);
In this case, your classes become:
public class A {
private B b;
public A(B b) { // Spring will autowired by magic when calling the constructor
this.b = b;
}
public void doSomething() {
b.doSomeThingElse();
}
}
#Component
public class B {
private C c;
public B(C c) {
this.c = c;
}
public void doSomethingElse(){
c.doIt();
}
}
How do you initialize this:
class A {
final B b;
A(B b) {
this.b = b;
}
}
class B {
final A a;
B(A a) {
this.a = a;
}
}
DI framework, reflection, better design?
Motivation and a use case (added):
My particular use case is simplifying field access in A's and B's sub-classes. So I'm injecting them to shortly reference them by fields in the derived classes without a need to declare explicitly in each sub-class.
There is also a recommendation on DI that objects should better be immutable: Guice best practices and anti-patterns.
You could use a factory method
class A {
final B b;
A(B b) {
this.b = b;
}
}
abstract class B {
final A a;
B() {
this.a = constructA();
}
protected abstract A constructA();
}
public class C {
public static void main(String []args){
new B(){
protected A constructA(){
return new A(this);
}
};
}
}
Though it may look dirty, but I prefer to replace one of the final references with Supplier (like one in Guava or Java 8) like:
class A {
final Supplier<B> b;
A(Supplier<B> b) {
this.b = b;
}
// keeping this constructor just for usability's sake
A(B b) {
this.b = ofInstance(b); // using Guava's Suppliers.ofInstance here
}
}
class B {
final A a;
B(A a) {
this.a = a;
}
}
public static void main(String[] args) {
// using MutableSupplier.create() static factory method
MutableSupplier<B> bRef = create();
A a = new A(bRef);
B b = bRef.set(new B(a));
}
where MutableSupplier looks somehow like the following:
import com.google.common.base.Supplier;
public class MutableSupplier<T> implements Supplier<T> {
private boolean valueWasSet;
private T value;
private MutableSupplier() {
}
#Override
public T get() {
if (!valueWasSet) {
throw new NullPointerException("Value has not been set yet");
}
return value;
}
public T set(final T value) {
if (valueWasSet) {
throw new IllegalStateException("Value has already been set and should not be reset");
}
this.value = value;
this.valueWasSet = true;
return value;
}
public static <T> MutableSupplier<T> create() {
return new MutableSupplier<T>();
}
}
I know that MutableSupplier's mutability looks super-ugly for immutability enthusiasts but I found that using it is more or less acceptable in such cases :)
What you are having is a circular dependency. The only way I can think of is to not declare the fields as final and have your dependency injected using setter injection instead of constructor injection.
A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
I am trying to cast a child to a sibling in Java (though I'm not sure if this is allowed). Basically what is written below:
public interface BaseInterface {
public int a = 5;
}
public class ClassA implements BaseInterface {
public int a = 3;
}
public class ClassB implements BaseInterface {}
public static void main(String[] args) {
BaseInterface a = new ClassA();
ClassB b = (ClassB) a;
}
I keep getting a ClassCastException. I am trying to copy all member variables from the BaseInterface object a to b. Can someone provide a solution on how to do this? Thanks!
This is not possible. Instead, you should give ClassA and ClassB copy constructors taking a BaseInterface:
public class ClassB implements BaseInterface {
public ClassB(BaseInterface other) {
//copy state from other instance
}
}
public static void main(String[] args) {
BaseInterface a = new ClassA();
ClassB b = new ClassB(a);
}
Of course this means you're copying to a new object instead of converting, but it's the only option if you want to go from a ClassA to a ClassB.
A ClassA is not a ClassB, so of course this is not allowed. Even if you suppress all warnings/errors and get the code to compile, at runtime the cast will cause a ClassCastException.
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
public interface BaseInterface {
public int getA();
}
public class ClassA implements BaseInterface {
private final int a;
public ClassA(int a) {
this.a = a;
}
public int getA() {
return a;
}
}
public class ClassB implements BaseInterface {
private final int a;
public ClassB(BaseInterface baseInterface) {
this.a = baseInterface.getA();
}
public int getA() {
return a;
}
}
public static void main(String[] args) {
BaseInterface a = new ClassA(5);
ClassB b = new ClassB(a);
}
Will do what you want. As others noted, casting will always give a ClassCastException.
Suppose I have a class A and a class B.
public class A {
private B b;
public A() {
this.b = new B();
}
public B getB() {
return this.b;
}
}
public class B {
public String getSome() {
return "Get some!";
}
}
I know I can get B through A, because A has (or owns) B: new A().getB().
But if I have B, can I get A?
Sure, just add routine getA() in you class B, and change the line in your constructor to
public A() {
this.b = new B(this);
}
This of course assumes your class B has a constructor which accepts an A, e.g.,
public B(A a) {
this.a = a;
}
B needs an explicit reference to its owner:
public class B {
private final A owner;
public B(A owner) {
this.owner = owner;
}
public A getOwner() {
return owner;
}
}
And in A:
public A() {
b = new B(this);
}
Nope. There is no such thing as an 'owner' in Java. Any object can be referenced by any number of other objects.
If you need B to always be bound to an instance of A, make B an inner class of A:
class A {
B b = new B();
class B {
String getSome() {
// this will refer to the enclosing A
return A.this.toString();
}
}
}
An inner (non-static) class always has an implicit reference to the enclosing instance and cannot exist without it. In order to instantiate B from outside, you need a nasty syntax: B b = new A().new B();
No you cannot. B has no reference to A.
No.
Class a has reference to class B, but class B has no reference to class A. References are one way only.
No, that's not possible. You're looking for backreferences, but we have to create them in the code if needed.
If you want to collect all referencers to B, you could do this with a constructor or with a factory (pattern) that creates B's. I'll show the factory:
public class B {
private static Set<? extends Object> referencers = new HashSet<? extends Object>();
private B(){} // no public constructor
public static create(Object parent) {
// cooperative approach, the caller should pass "this"
referencers.add(parent);
}
public static remove(Object parent) {
referencers.remove(parent);
}
}
you can also use inner classes
package test;
public class A {
B b = null;
public B getB()
{
return b;
}
public class B {
public A getA()
{
return A.this;
}
}
public static void main(String[] args) {
B b = new A().new B();
}
}