Niharika Dash
Niharika Dash

Reputation: 59

How to mock Abstract class method in a class to be tested

There is an abstract class

public abstract class BaseProcessor {
 public BooksTransaction getBooksTransaction() {
        return booksTransaction;
    }
}

There is another final class which is to be tested using Junit

public final class CreateOrganisationProcessor extends BaseProcessor {

public boolean process() throws Exception { //method to be tested
        request = new CreateOrganisationRequest(IntegrationSystems.valueOf(getBooksTransaction().getSource()),
                IntegrationSystems.valueOf(getBooksTransaction().getDestination()), getBooksTransaction()); 
        request.setRequestTypes(getRequestTypes());
return true;
}
}

I tried spying the BaseProcessor class and mocking getBooksTransaction method to return BooksTransaction Object. Code:

@Test
   public void testProcess() throws Exception {
BaseProcessor spy = Mockito.spy(new CreateOrganisationProcessor());
       BooksTransaction booksTransaction = new BooksTransaction();
       booksTransaction.setReferenceID(DEFAULT_REFERENCE_ID);
       Mockito.doReturn(booksTransaction).when(spy).getBooksTransaction();
}

Here, BooksTransaction is an JPA Entity class.

However, when I run the test case, the mock does not seem to be working, it does not return a BooksTransaction Object. It neither throws an exception, nor any error.

I would like to know the right way to spy this method so that it returns me an object of BooksTransaction as per my mock.

I am new to Mockito, any help would be appreciable. Thanks in advance.

Upvotes: 5

Views: 3334

Answers (1)

Eugene
Eugene

Reputation: 120858

It's funny that you got 5 up-votes for a question that does not even compile to begin with... I have simplified it just a bit, so that I could actually compile it, since I do not know your structure or can't even guess it correctly.

But the very first point you should be aware of is that Mockito can't by default mock final classes; you have a comment under your question that shows how to enable that.

@Getter
static abstract class BaseProcessor {
    private BooksTransaction BooksTransaction;
}

@Getter
static class CreateOrganisationProcessor extends BaseProcessor {

    CreateOrganisationRequest request;

    public boolean process() { //method to be tested
        request = new CreateOrganisationRequest(getBooksTransaction());
        return true;
    }

    public CreateOrganisationRequest getRequest() {
        return request;
    }
}


@RequiredArgsConstructor
@Getter
static class BooksTransaction {
    private final String testMe;
}

@Getter
@RequiredArgsConstructor
static class CreateOrganisationRequest {
    private final BooksTransaction booksTransaction;
}

And here is a test that does work:

@Test
public void test() {
    CreateOrganisationProcessor org = new CreateOrganisationProcessor();
    CreateOrganisationProcessor spy = Mockito.spy(org);
    System.out.println(spy);
    BooksTransaction booksTransaction = new BooksTransaction("go!");

    Mockito.doReturn(booksTransaction).when(spy).getBooksTransaction();

    spy.process();
    BooksTransaction mocked = spy.getRequest().getBooksTransaction();
    Assert.assertEquals(mocked.getTestMe(), "go!");
}

And now think about it, you say in a comment : //method to be tested but you are not even calling it in your test, sounds fishy doesn't it? Than that method is defined in CreateOrganisationProcessor, but you are assigning your spy to:

 BaseProcessor spy = Mockito.spy(new CreateOrganisationProcessor());

So now you can't even call process anymore on that spy reference, since it is not defined in BaseProcessor.

Upvotes: 1

Related Questions