Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito Mocking a return value and verify it

I have this class and wants to create a mock to return and verify the return value "50":
QAService.java:

@Path("/QAService")
public class QAService {
@GET()
//@Path("/")
@Produces("text/plain")
public String getServiceInfo() {
    return "50";
}

My understanding of mock by defintion is that I can create a fake object of an implementation class and mock functions yet to be developed so I can test the interface.

Still I am creating this test to test mocking without having an interface. How do I verify it?:
QAServiceTest.java:

public class QAServiceTest {

    @Test
    public void getserviceTest () {

    QAService qasmock = mock(QAService.class);
    when(qasmock.getServiceInfo()).thenReturn("50");
    String expected = "50";
    assertEquals(expected, qasmock.getServiceInfo());
    }
}
like image 919
JustinBieber Avatar asked Feb 28 '14 15:02

JustinBieber


People also ask

How does verify work in Mockito?

Mockito verify() method can be used to test number of method invocations too. We can test exact number of times, at least once, at least, at most number of invocation times for a mocked method. We can use verifyNoMoreInteractions() after all the verify() method calls to make sure everything is verified.

Does Mockito verify use equals?

Mockito verifies argument values in natural java style: by using an equals() method.

How does Mockito when then return work?

Mockito when() method It enables stubbing methods. It should be used when we want to mock to return specific values when particular methods are called. In simple terms, "When the XYZ() method is called, then return ABC." It is mostly used when there is some condition to execute.

How do I return an object in Mockito?

In Mockito, you can specify what to return when a method is called. That makes unit testing easier because you don't have to change existing classes. Mockito supports two ways to do it: when-thenReturn and doReturn-when . In most cases, when-thenReturn is used and has better readability.


2 Answers

Let's get a couple definitions straight, first:

  • A unit test is a brief bit of code you write to ensure that the system you've developed is behaving correctly. Unit tests are often created in a framework like JUnit, but do not need to be. For example, a unit test would assertEquals(5, calculator.add(2, 3)).

  • A mock is an imitation of a real system, which is often used in unit tests. Mocks are often created in frameworks like Mockito or EasyMock, but do not need to be. Mocks are a form of "test double"—the general term for code you substitute in place of your actual systems, for testing purposes—and Martin Fowler defines them more exactly in an article called "Mocks Aren't Stubs".

  • When writing a unit test, you're trying to test a single unit, which is often called the system under test or SUT for short. Each test will probably have a different system under test, and the point is that the code that you are testing in the test is your real, actual code, not any sort of mock or fake implementation.

  • In a complex application, your classes will probably need to collaborate with other classes that may or may not be written or tested, which are categorically known as dependencies. Any given class or system may have its own dependencies, and may be a dependency for other systems. Mocking frameworks are good for mocking those dependencies, not for mocking the system under test.


For your example, QAService is the main class you're writing (system under test), and QAServiceTest is the unit test for that system. No mocks are necessarily required.

Let's say that QAService depends on another class not yet written, called "StorageService". You don't necessarily want to wait for StorageService to work before writing QAService's tests, so instead of using a real StorageService you use a mock. Again, in the unit test called QAServiceTest, you use a real QAService and mock its dependency StorageService.

Even though you don't have StorageService written, you probably have some expectation about how QAService will use that class. Maybe you know that when you call storageService.store(qaRecord), it should return a numeric ID like 101. Even without the code working, you can create a Mockito mockStorageService, and prepare it like this:

when(mockStorageService.store(expectedQARecord)).thenReturn(101);

Now let's say that at the end of the test, you want to ensure that the method of QAService that you're testing will absolutely call storageService.delete(101). A Mockito mockStorageService would check that like this:

verify(mockStorageService).delete(101);

It is often unnecessary to verify statements you have made with when, because the test is unlikely to succeed unless the system under test calls the mock correctly to get that return value (101 here).

Now let's say that you've written another block of code called QAApplication, which you're testing in a unit test called QAApplicationTest, that depends on QAService. You may not have QAService finished or tested, and using a real QAService would require a StorageService, so instead you use mock QAService with a real QAApplication in your unit test called QAApplicationTest.


So, to sum up, a mock works within unit tests to mock the dependencies of the system under test. In your situation, QAServiceTest will not need a mock QAService, but may be used to mock the dependencies of QAService. If you do need a mock QAService, you'll need it when testing another class where QAService itself is a dependency.

like image 96
Jeff Bowman Avatar answered Oct 12 '22 21:10

Jeff Bowman


Junit will only run methods annotated with @Test, so add it

@Test
public void getserviceTest () {
    QAService qasmock = mock(QAService.class);
    when(qasmock.getServiceInfo()).thenReturn("50");
    String expected = "50";
    assertEquals(expected, qasmock.getServiceInfo());
}

Also, you should verify() that your mock expectations actually happened.

verify(qasmock, times(1)).getServiceInfo();

Note that it seems like you want to test QAService, but you really aren't doing that here. You are simply testing a mock. That's not the same thing.

Create the QAService object yourself and use it.

like image 21
Sotirios Delimanolis Avatar answered Oct 12 '22 23:10

Sotirios Delimanolis