0

I am new to mockito. Lets say I have a class like this

public class MyClass {
    int a;
    String b;
    public MyClass(int a) {
        this.a = a;
        this.b = draw();
        System.out.println("class is created");
    }

    public String draw() {
        System.out.println("my");
        return "b";
    }

    public void apple() {
        System.out.println("apple");
    }
}

I am writing a JUnit test using Mockito where I am creating a object of the class by using the constructor. Is it possible to mock the draw() method when I am instating the class?

Dmytro Maslenko
  • 2,247
  • 9
  • 16
  • Can you share your test's code, or at least the relevant parts of it? – Mureinik Sep 26 '17 at 19:23
  • What are you trying to achieve? Your class under test doesn't have any dependency on another object. So there is nothing to mock. – JB Nizet Sep 26 '17 at 19:24
  • you don't always have to use mockito. For your case why you need to mock anything. use simple junit test. – want2learn Sep 26 '17 at 20:15
  • Since you are writing tests, you probably aim for writing testable code. If so, you should avoid constructors doing more then merely assigning parameters to fields. See [here](http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/) for an excellent argumentation on this topic. – Frank Neblung Sep 27 '17 at 07:24

4 Answers4

6

Not clear why you need the Mockito here. This is a solution without Mockito.

In your test create an instance of MyClass with overridden draw() method:

final MyClass myClass = new MyClass() {
    @Override
    public String draw() {
        return "mock data";
    }
}

// Now test your class as you want
Dmytro Maslenko
  • 2,247
  • 9
  • 16
1

You could turn to do partial mocking using spies (see here for how to do that).

But as usual: when people start thinking about complex ways to use mocking framework, the real answer is: step back and improve your production code. Your constructor should do only simple initialisation things.

In your case, one reasonable approach would be: don't call an internal method to compute the value of that field - but pass that value to the constructor (in other words - use dependency injection).

And you could still do something like:

public MyClass(int a) {
  this(a, draw());
}

MyClass(int a, String b) { 
  this.a = a; ...

Now your unit tests can happily use that ctor that takes two arguments - and your need to mock anything vanishes completely.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
0

One way to test your class with Mockito will be,

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

public class TestMyClass {

    @Mock
    private MyClass clazz;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testDraw() {
        when(clazz.draw()).thenReturn("My mock hello");
        assertEquals("My mock hello", clazz.draw());
    }
}
Indra Basak
  • 7,124
  • 1
  • 26
  • 45
0

Complementing the solutions given, the constructor can also receive the method to mock as a function.

import java.util.function.Supplier;
    
public class MyClass {
    int a;
    String b;

    public MyClass(int a, Supplier<String> draw) {
        this.a = a;
        this.b = draw==null? draw() : draw.get();
        System.out.println("class is created");
     }
        
    public String draw() {
        System.out.println("my");
        return "b";
    }
        
    public void apple() {
         System.out.println("apple");
     }
}
ejaenv
  • 2,117
  • 1
  • 23
  • 28