Different ways of mocking object creation in Mockito? - java

I see a couple different ways of mocking objects. What exactly are the differences between this approache using InjectMocks and the approach shown here: https://github.com/mockito/mockito/wiki/Mocking-Object-Creation?
#ExtendWith(MockitoExtension.class)
public class MyTest() {
#Mock ClassB uut;
#InjectMocks ClassA cA;
#Test
public TestOne() {
...
}
}
where
public class ClassA() {
public ClassA() {
ClassB temp = new ClassB();
}
}
versus the method shown here:
https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
What exactly is the difference?

I believe there is no essential difference between those approaches.
InjectMocks approach
Actually for it to work, your class should accept the dependencies through the constructor or setters (and it never works with both). I would say that this approach makes the testing easier because you inject whatever you want to your class object at the initialization phase.
class Foo {
private final Bar bar;
public Foo(final Bar bar) {
this.bar = bar;
}
}
If this is our class under test, then all #InjectMock does is to create mocks, and do the following:
Foo foo = new Foo(barMock);
Apart from being testable, imagine if the Bar is an interface, then you can possibly you can switch between multiple implementations of it without actually touching the class code (ideally). If you have a DI framework, that's even easier. So, basically this format of the class makes it flexible.
Using one-line methods for object creation
Let's say this is our class under test. As you can see, I am initializing the property inside the constructor. Legally, with no reflection magic, I cannot put a mock bar variable neither during initialization nor after that.
class Foo {
private final Bar bar;
public Foo() {
this.bar = new Bar();
}
}
The reason that Mockito docs tell you to switch to either a one-liner method or a Factory helper is that:
Mockito cannot mock constructors, which means you cannot put a mock object in the place of bar without reflection, and you can only do that after the initialization. Generally, to point of my view on testing, reflection should be avoided as much as possible.
One-liner functions are looking as clean as constructors and they can be descriptive (like static factory methods).
So, when you switch your class to look like this:
class Foo {
private final Bar bar;
public Foo() {
this.bar = makeBar();
}
Bar makeBar() {
return new Bar();
}
}
Now, you can put a spy, and just mock the makeBar method easily. The same applies to the factory method as well. To be honest, the factory approach looks a bit wordy to me, but still, I am sure there will be times when it may come handy.

Related

Injecting a Bar with an already existing Foo

Consider the existence of a Foo some time in the app. Now Bar objects depend on a Foo. I want to create this bar based on this foo I already have, but Guice creates a new instance of Foo every time. I can have a lot of Foos, so I cannot #Singleton Foo.
I tried to use scopes for this purpose, but I don't know what I am doing wrong.
I know this can be solved with #AssistedInject but I do not want to take this solution because these associations are common in my context and the dependency is only one. Also, since I am working on creating a tool based on Guice, all I got is a Foo, and Bar.class and I want to create instances of Bar with the given Foo. I am not aware if there are any factories or so.
public class InjectionTest2 {
public static void main(String[] args) {
Module module = new AbstractModule() {
ReceiverScope receiverScope = new ReceiverScope();
#Override
protected void configure() {
bindScope(ReceiverScoped.class, receiverScope);
bind(Foo.class);
}
#Provides
#Singleton
public ReceiverScope scope() {
return receiverScope;
}
};
Injector injector = Guice.createInjector(module);
Foo foo = injector.getInstance(Foo.class); //assume a given foo
ReceiverScope scope = injector.getInstance(ReceiverScope.class);
scope.enter();
scope.seed(Key.get(Foo.class, Existing.class), foo);
Bar bar = injector.getInstance(Bar.class);//Create a Bar with this foo
scope.exit();
}
private static class Foo {
#Inject
public Foo() {
System.out.println("foo created" + toString());
}
}
#ReceiverScoped
private static class Bar {
#Inject
public Bar(#Existing Foo foo) {
System.out.println("bar created with foo" + foo.toString());
}
}
#Retention(RetentionPolicy.RUNTIME)
#BindingAnnotation
private static #interface Existing {
}
}
ReceiverScope is a class identical to Simple Scope given here.
Another way I can think of is if I manually iterate Bar's contructor parameters and for each parameter, I ask guice to give me an instance, but if it is a Foo, I give my value. But won't this give me a very hard time? I mean I will have to consider a lot of things, because in the constructor might be extra Qualifiers on parameters and stuff...
EDIT (after #kendavidson's answer):
This is true. I thought it makes my question more complicated, that's why I did not include it. Bar is an interface. Fields in Foo contain an annotation which has a Class<? extends Bar> barClass() method. For example:
#ContainsBars
private static class Foo {
#MakeBar(BlueBar.class)
private Something aSomething;
#MakeBar(BlackBar.class)
private SomethingElse aSomethingElse;
#Inject
public Foo() {
//create aSomething
//create aSomethingElse
}
}
Now, whenever Guice injects a #ContainsBars, I listen it via a TypeListener and I go to create the bars. I scan Foo.class and I get BlueBar.class & BlackBar.class.
The problem I am trying to solve is, how to create BlueBar when BlueBar has a dependency to Foo.class? Whenever this happens, I need to create the BlueBar with the Foo I was taken from the listener.
Reflecting constructor was one of my thoughts however it sounds a pain in the ... I guess, it will need to iterate each parameter of the #Inject constructor of BlueBar.class. If the parameter is of type Foo, I give my Foo. If it is a different type, ask the injector to give me an instance of that type. The thing is, how do I do this. When Guice injects, it takes in consideration possible binding annotations (Qualifiers) and generics. Doing that again, sounds pain.
In the other hand, these #ContainsBars annotated classes by 99% chance have no relation to each other.
Adding a method to Bar interface like setFoo(Foo f) will not work. It will have to be a generic. Therefore, method injection with a setter will be cast unsafe. As far as I am aware of, and assuming BlackBar implements Bar<Foo>, when I will Bar b = injector.getInstance(BlackBar.class), It will give me a Bar<?>. That means, I can't call the setter safely.
Field injection is interesting. Having something like this:
public class BlackBar implements Bar {
private MyDepedency dep;
#Existing
private Foo foo;
public BlackBar(Foo foo,MyDepedency dep) {
this.foo = foo;
this.dep = dep;
}
}
seems ok. Whenever, I get a BlackBar, I go find the #Existing field, and then set the value. I do not care for the value in constructor. Let's say:
Foo foo = ...
Bar bar = injector.getInstance(BlackBar.class);
setExistingFieldWithValueOf(foo,bar);
The problem here is that whenever I ask injector, it sees the Foo dependency, and it is creating a new Foo in order to inject. Then, I go change its value. This will cause an infinite loop since during Foo injection which is a #ContainsBar, the process will be repeated. Even if i manage to stop the infinite loop, still the creation of a new Foo that will never be used seems a bad overhead. If there is a way to inject with null value to foo in the constructor, let me know. I will use this.
This might be a shot in the dark and if I'm missing something please let me know. First off, I definitely think AssistedInject is a solid choice, with a minimal footprint for each Bar.
A couple things missing from your question and comments are:
What are some sample annotated fields of Foo?
How do you expect multiple Bars to be created?
Are you dealing with Bar and OtherBar implementations? Or are you dealing with Bar and <T extends Bar> interface?
Based on some of these things, it might be doable with:
// BarProvider.java
public class BarProvider {
// Get the injector, frowned upon but required
#Inject Injector injector;
public <T extends Bar> T get(Foo foo, String fieldname) {
// Provider right now returns on Bar at a time, I'm guessing this is based on
// fieldname, which can lookup the #Annotation to get the class
Annotation annotation = ...;
Bar bar = ...;
// Now you need to create the bar, this can be done in a couple of ways:
// Option 1 is to reflect the Bar(Foo) constructor
// then doing an injector.injectMembers(bar) to fill the remaining fields
// Option 2 is to use field/method injection and doing a combination of
// Bar bar = injector.getInstance(annotatedClass); followed by
// bar.setFoo(foo);
return bar;
}
}
// Foo.java
public class Foo {
}
// Bar.java
public interface Bar {
}
// ABar.java
public class ABar {
}
// BBar.java
public class BBar {
}
In both cases you would not #Inject the Foo field in Bar. Again this makes some assumptions on how you know which field you want to look at in Foo for the annotation class type.
Another option would be to return all of them using:
public <T extends Bar> T[] get(Foo foo) {
// Same thing but loop through all Annotated fields
}
In both cases I'm assuming that Bar and OtherBar are actually implementations of the same interface which means you'd always be using Bar as a return type. It's still possible otherwise, just a little more annoying.
Hopefully I'm not way off base, and something might be helpful. But again AssistedInject the way it was described above would still probably be a better solution.
Edit 1 - Circular Dependencies
If you have these classes, for example, you will not have issues with Foo being injected and then overwritten.
public abstract class Bar<T> {
T foo;
setFoo(T foo) {
this.foo = foo;
}
}
public class BlackBar extends Bar<Foo> {
#Inject Dep1 dep1; // Injected
#Inject Dep2 dep2; // Injected
BlackBar() {}
}
#ContainsBar
public class Foo {
#BlackBar
SomeObject someObject;
}
Now in your example:
Foo foo = injector.getInstance(Foo.class); // Inject SomeObject
Bar bar = injector.getInstance(BlackBar.class); // Inject Dep1 and Dep2
bar.setFoo(foo); // Set Foo manually
This won't cause the problem you think it does, because Foo foo is NOT annotated with #Inject therefore Guice won't create a new one when building BlackBar.
But this still doesn't answer how exactly you're USING your bars. I also have a feeling I'm missing something very important to the end goal.

Is this the good class design practice in Java?

public class OneClass {
private AnotherClass anotherClass = new AnotherClass();
private void doOneJob(){
anotherClass.doOtherJob();
}
}
In the above code, AnotherClass is instantiated and held as a class variable of OneClass.
What are the consequences of this design?
Is it a good practice?
Will this support unit testing?
This is called composition and is a fundamental part of Java language. There is nothing wrong with it, and might be essential in a lot of cases.
The only change I would do is use dependency injection to make it easier for testing, i.e. you'll be able to supply a mock AnotherClass object this way:-
public class OneClass {
private AnotherClass anotherClass;
public OneClass(AnotherClass anotherClass){
this.anotherClass = anotherClass;
}
private void doOneJob() {
anotherClass.doOtherJob();
}
}
It is hard to "unit" testing because you cant mock the "external" dependency in a normal way. (With groovy tests for example you can override private fields with a mock)
I think it would be better that you have a constructor that accepts a AnotherClass than you can mock it in a unit test via constructor.

Guice field injection

So here's the thing. I'm trying to inject some fields with guice, but it turns out that they are always null (not trying to use them on the constructor).
public class A {
#Inject
private SomeClass bar;
public A() {
foo();
}
public someMethod() {
bar.doSth();
}
}
public class B {
private A a;
public B() {
a = new A();
}
public someOtherMethod() {
a.someMethod();
}
}
Now whenever the app executed someOtherMethod and a tries to run bar.doSth a nice NullPointerException is raised.
So in order to fix this i ended Injecting the field manually inside the constructor:
public A() {
final Injector injector = Guice.createInjector();
bar = injector.getInstance(SomeClass.class);
}
But this is ugly, unclear, has a lot of boilerplate and I'm forced to do it on many places which make it tedious.
Is there any other way to archive this? Or an explanation of why the field is not being injected?
Thanks
Note:
I'm currently unavailable to do the propper injection on the constructor (with bar as a parameter) because of the refactoring it would imply. The project is now under heavy production and thus this kind of refactoring can't be done right now.
The IOC container only controls what you tell it to control. It doesn't know about the A inside of B, because it's being constructed directly, not managed by the container. You need to inject the A as well:
public class B {
#inject private A a;
public B() {}
...
}
And you can't just call new B() either, you need to inject the B as well.

Dagger2 + Mockito: How to Unit Test this scenario?

I'm working on a team project which has a very coupled code. I'm trying to increase the unit test coverage and I've faced the following scenario:
class Foo {
static void methodA () {
Bar b = new Bar();
b.getContent();
}
}
class Bar {
#Inject
DBAcessor mDBAcessor;
Bar () {
Dagger2.getInjector().inject(this);
}
public Object getContent() {
mDBAcessor.fetchData();
}
}
I want to unit test methodA(), however I don't know if it is possible to do it without passing the DBAcessor object via constructor to Bar() class. Bar should be a POJO model being widely used throughout the project, hence, I don't know if it would be a good idea to change its constructor and impact so many other classes. Any tips on how should I approach this scenario?
That is wrong design.
Whenever you have an access to the constructor, pass class dependencies into constructor. That really eases unit testing. Class Bar should look:
class Bar() {
#Inject DBAcessor mDBAcessor;
Bar (DBAcessor dbAcessor) {
this.mDBAcessor = dbAcessor;
}
public Object getContent() {
mDBAcessor.fetchData();
}
}
Dagger2 methods declared in Component should only be used inside object you don't have an access to the constructor (Activity or Fragment).
Then nothing prevents you from doing that:
DBAccessor dbAccessor = Mockito.mock(DBAccessor.class);
Bar bar = new Bar(dbAccessor);
bar.getContent();
verify(bar, times(1)).fetchData();
If you really need to stick to such design, then you can't make unit tests on such object, as Dagger2 depends on Application object, which needs Context, which you cannot emulate in unit tests. Write your test as androidTest, create appropriate Activity, fetch Bar object from it and test it.

Mocking autowired field in the method

I was wondering whether there's a way to mock the field which is being autowired.
Consider the following case.
I have a class name A
public class A {
#Autowired
private B b;
public void aMethod() {
b.method();
}
}
The other class B looks like this
public class B {
public void method() {
// some code
}
}
Now i want to write junit for the method.
I know there's a way to mock the autowired field like this.
public class TestA {
#InjectMock
private A a;
#Mock
private B b;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
public void testAMethod() {
// write test case.
}
}
But my question is -> Is there a way to mock the autowired field inside method after creating object with new.
eg
public class TestA {
public void testAMethod() {
A a =new A();
// how to mock the B instance in it.
}
}
Please suggest or there's no way to do this????
I dont want to change from private modifier. Nor i want to add getter's and setters or reflection. I just want to know is there a way to mock the B instance after creating the new object of A class.
How about ReflectionTestUtils?
A a = new A();
B b = mock(B.class);
ReflectionTestUtils.setField(a, "b", b);
It's still reflection-based and has all related drawbacks, though it's quite simple and easy to read.
You can not do that with mockito, this would require to modify the bytecode of the class being tested. However Powermock allows such stubs. Note though that I and the creator of Powermock - Johan Haleby - would push for a refactoring instead of using Powermock. Powermock is very powerful, maybe too much, and working allows anyone to write legacy code, that would be difficultly maintainable or extensible (property you can find in poorly designed legacy code).
In your case I don't know what's wrong in your case with the dependency injection. However if the code need a new instance of B, it may be useful to have inject in A a factory/provider/builder class which will make a new instance of B. Such code can be easily stubbed with Mockito.

Categories

Resources