-2

I am fairly new to mockito framework. I've been reading upon multiple tutorials in regards to it. One of them I was following is this: https://www.tutorialspoint.com/mockito/mockito_first_application.htm

There is a statement creating a mock of Stock Service.

In this example, we've created a mock of Stock Service to get the dummy price of some stocks

My question is Stock Service is a real service class or mock service class you have to manually stand up for mimicking the real service class. I am a bit confused. Having basic understanding of junit framework. What I had practiced before was if there is a service class Foo then I used actual class that provides all the exposed methods.

public class Foo {

    public Foo() { } // construtor

    public String returnAddress(String userId) {
        // ...
        return dataAccesobj.getAddress(userId);
    }
}

Calling foo.returnAddress(..) in unit test if I remember right.

The reason I am asking this question is while I was working with mockitoto create a test method for a class, I ran into a unique(?) challenge.

I started with a real service class which depends on its super class constructor to return its instance. The challenge I ran into was this super class constructor initiates DB connection and loading/parsing properties files which I do not need for my test. I was thinking about how to prevent DB connection and loading/reading prop files....

I thought I read from one of mockito tutorials you can isolate testing without having such services. I tried with @Mock and @Spy (not fully understanding well still what they are for..) but it didn't make a difference for output (maybe I misused those annotations).

So what I did was actually creating fake/mock class out of real service class (e.g. Foo) by simply copying it and renamed it as FooMock and put it in src/test/java folder in where unit test class is running from. I kept the mock class exactly same as the real service class except taking out unwanted logic such as db connection or loading/reading prop file for env specific. By doing that I was able to test one of exposed methods that read ldap directory...

I am sorry I got digressed but hope my point is clear at this point. I am not sure the way I handled this situation is right or wrong. I'd appreciate experienced engineers would clarify the way I handled the matter is acceptable in mockito way or not. If not, then plz advise me best way to handle it.

DaeYoung
  • 1,161
  • 6
  • 27
  • 59
  • `Foo mockFoo = Mockito.mock(Foo.class)` ... when you call that you see it calling the constructor? Per [this question](https://stackoverflow.com/questions/7173358/is-mockito-supposed-to-call-default-constructor-of-mocked-class) mockito does not call the constructor itself. It's not clear to me what your issue is. – Roddy of the Frozen Peas Dec 14 '18 at 16:36
  • My apology if laid description is not clear. Yes, it triggers `Foo`'s private constructor which invokes `super()` of its parent class. btw - `Foo` class uses singleton pattern. I used annotation `InjectMocks` instead to return `Foo` instance btw. – DaeYoung Dec 14 '18 at 16:43
  • I tried `Foo fooMock = Mockito.mock(Foo.class)` then it threw an exception `Cannot mock/spy class Foo Mockito cannot mock/spy following: final classes`. It is indeed `final` class. – DaeYoung Dec 14 '18 at 16:52
  • You might consider PowerMockito to work around the final class restriction. – Roddy of the Frozen Peas Dec 14 '18 at 16:53

1 Answers1

0

With Mockito, a mock is an implementation of a wrapper class. The mock object "wraps" the target of the mock (the service in your example) and allows you to define functionality of each method.

There are two mocked functionality options with Mockito; call the wrapped method and don't call the wrapped method.

I don't know when it would make sense to call the wrapped method, so I always use don't call the wrapped method.

After you create the mock, use the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) method to mock functionality.

Edit: some more info.

I will assume that you are using junit v4. The details of this will differ based on the the junit major release number, but the actual work will be the same.

  1. Use annotations to define your Mock objects (@Mock), except in a few special cases. This will create mocks of non-final classes, abstract classes, and interfaces.
  2. Create a "before-test" method using the @Before annotation; I traditionally name this method preTestSetup, but the actual name does not matter.
  3. Call MockitoAnnotations.initMocks(this) as the first line of code in the "before-test" method. This will find the @Mock annotations and instantiate a mock for each.
  4. Use the ReflectionTestUtils.setField method to inject the mocks into your object (assuming that you don't have setter methods, which I traditionally don't like).
  5. Define the mocked functionality of each method using the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) technique.

Here is some example code (caveat: this should be fully functional, but I did not compile it):

public interface MyService
{
    String blammy(SomeParameter parameter);
}

public class UsesMyService
{
    @Autowired
    private MyService myService;

    public String kapow(final SomeParameter parameter)
    {
        return myService.blammy(parameter);
    }
}

public class UnitTestUsesMyService
{
    private UsesMyService classToTest;

    @Mock
    private MyService mockMyService;

    @Mock
    private SomeParameter mockSomeParameter;

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

        classToTest = new UsesMyService();

        doReturn("Blam").when(mockMyService).blammy(mockSomeParameter);

        ReflectionTestUtils.setField(
            classToTest,
            "myService",
            mockMyService);
    }

    @Test
    public void kapow_allGood_success()
    {
        final String actualResult;


        actualResult = classToTest.kapow(mockSomeParameter);


        assertNotNull(actualResult); // Not strictly necessary.

        assertEquals(
            "Blam",
            actualResult);
    }
}
DwB
  • 37,124
  • 11
  • 56
  • 82
  • I am still struggling with how to obtain mock object properly in my case but `Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) method to mock functionality.` sounds promising to me. I will test it with current mock object I have obtained unorthodox way. Ty for your suggestion! – DaeYoung Dec 14 '18 at 17:23
  • Ty for taking your precious time to enhance your answer to help me out. Some parts I think I understand but some I do not. Having `private` class, I can't `mock` it so I decided to use `junit` instead although `powermock` is suggested but due to a reason I can't go with it. – DaeYoung Dec 17 '18 at 14:53