5

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.

  • Mocking of final class is not supported by default, but can be enabled if you use a mockito version that supports this feature. Check this [`answer`](https://stackoverflow.com/a/40018295/11514534) and/or the [`faq`](https://static.javadoc.io/org.mockito/mockito-core/3.0.0/org/mockito/Mockito.html#Mocking_Final) instead. – second Aug 28 '19 at 18:55
  • @second that `final` class _will_ result in a very specific error message; that the OP does not get. – Eugene Aug 28 '19 at 19:33

1 Answers1

1

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.

Eugene
  • 117,005
  • 15
  • 201
  • 306
  • I did not add the `assert` statement where I am calling process to keep the question short. There are a lot more mocks to be done before calling the process method. But the first line `getBooksTransaction` was throwing error which made me ask the question. I see that spy has been created on `CreateOrganisationProcessor` and not on `BaseProcessor`, what is the concept behind spy? could you explain in short please. also, it throws `NPE` when i run this code. At `getBooksTransaction()` . When I evaluate the expression in intellij it says 'this' is not available. – Niharika Dash Aug 29 '19 at 08:15
  • @NiharikaDash see how much sense you make. on one hand you say _But the first line getBooksTransaction was throwing error which made me ask the question_ in the comment, but you say in the question: _It neither throws an exception, nor any error._ Then you go ahead to say: _also, it throws NPE when i run this code, followed by _When I evaluate the expression in intellij it says 'this' is not available._. There's like 10 different things you are talking about. – Eugene Aug 29 '19 at 14:57