简体   繁体   中英

Different ways of mocking object creation in Mockito?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM