Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing abstract classes with arguments on constructor

Tags:

java

mockito

I'm trying to learn about tests but I'm facing some problems whilst testing abstract classes. I know I could create a concrete subclass that inherit from Dog, like ConcreteDog, but if I add a new abstract method to Dog, I would have to add a empty method to ConcreteDog so. That would not be so cool I guess.

public abstract class Dog {
  private final int id;

  public Dog(int id) {
    this.id = id;
  }

  public int getId() {
    return id;
  }

  public abstract void makeSound();
}

...

public class DogTest {
  @Test
  public void testGetId() {
    int id = 42;

    // How to pass id to Dog constructor ?
    Dog dog = Mockito.mock(Dog.class, Mockito.CALL_REAL_METHODS);

    assertTrue(dog.getId() == id);
  }
}

What I'm trying to do is somehow call the Mock with the constructor, like

Mockito.mock(Dog(id).class, Mockito.CALL_REAL_METHODS);

I don't know if it's possible with mockito, but there is a way of doing that using mockito or another tool ?

like image 963
tjbrn Avatar asked Oct 07 '16 00:10

tjbrn


2 Answers

You may just do this:

Mockito.mock(Dog.class, Mockito.withSettings()
        .useConstructor(999)
        .defaultAnswer(Mockito.CALLS_REAL_METHODS)
);

Where 999 - is any integer for id argument. So you don't have to inherit your abstract class anymore. You also may pass as many arguments as constructor needed e.g.:

.useConstructor(new Object(), "my string", 5.5, null)
like image 88
Aunmag Avatar answered Sep 23 '22 02:09

Aunmag


You can set the field using reflection if you need to, this essentially replicates how the constructor is setting the member fields.

Dog dog = Mockito.mock(Dog.class, Mockito.CALL_REAL_METHODS);
ReflectionTestUtils.setField(dog , "id", 42);
like image 34
UserF40 Avatar answered Sep 20 '22 02:09

UserF40