Mockito 3 Behavior Driven Development

Code flow is like a behavior for example if the user given options A and B, when user opts for A then C should be output or if opts for B then D respectively.

from above, we can deduce the user's behavior and create a test case to mimic user behavior, called Behavior Driven Development or BDD.

In order to create a BDD test case, Mockito provides us a new class BDDMockito with given, when and then methods.

Mockito#when and BDDMockito#given are technically same.

Mockito#when is already present and provides the exact same functionality that BDDMockito#given provides. if required we can use Mockito#when as well. Initially, the Mockito framework was more stub oriented hence term and vocabulary when was used to depict the stubs. so in technical terms test cases were created with when ... then ... style

Nowadays test cases have evolved from basic input and output to Behavior Driven Development or BDD, which is more focused on human behavior than technical terms. To depict human behavior vocabulary terms are an update to given ... then ... style.

package com.example.mokito3.sujan;

public class AppleService {

    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.BDDMockito.given;

@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void saveAppleWithoutMockTest() {
        // given
        given(appleService.saveApple("Macintosh")).willReturn("i eat apple");
        // when
        String macApple = appleService.saveApple("Macintosh");
        // then
        assertEquals("i eat apple", macApple);
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

Mockito#when vs BDDMockito#given

BDDMockito provides new ways to write test cases in given ... then ... style and help in Behavior Driven Development or BDD, but it doesn't mean we can use Mockito traditional way. In fact, there is very little difference between Mockito#when vs BDDMockito#given.

package com.example.mokito3.sujan;

public class AppleService {

    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }
}
Mockito#when BDDMockito#given
@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    /* Mock */
    @Mock
    private AppleService appleService;

    @Test
    void saveAppleMockTest() {
        /* When */
        when(appleService.saveApple("Macintosh")).thenReturn("i eat apple");
        /* Then */
        String macApple = appleService.saveApple("Macintosh");
        /* Verify */
        verify(appleService).saveApple("Macintosh");
        assertEquals("i eat apple", macApple);
    }
}
@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    /* Mock */
    @Mock
    private AppleService appleService;

    @Test
    void saveAppleMockTest() {
        /* Given */
        given(appleService.saveApple("Macintosh")).willReturn("i eat apple");
        /* Then */
        String macApple = appleService.saveApple("Macintosh");
        /* Verify */
        verify(appleService).saveApple("Macintosh");
        assertEquals("i eat apple", macApple);
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

For BDD or to mimic human vehaviour, we can use Inorder interface.

package com.example.mokito3.sujan;

public class AppleService {

    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }

    public String haveApple(int appleCount) {
        String appleString = "i have " + appleCount + " apple";
        return appleString;
    }

    public String eatApple(String apple) {
        String appleString = "i eat " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.times;

@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void appleMockTest() {
        InOrder inOrder = inOrder(appleService);
        appleService.saveApple("Macintosh");
        appleService.haveApple(2);
        appleService.eatApple("Macintosh");
        appleService.eatApple("Macintosh");
        then(appleService).should(inOrder).saveApple("Macintosh");
        then(appleService).should(inOrder).haveApple(2);
        then(appleService).should(inOrder, times(2)).eatApple("Macintosh");
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

 

BDD when ... then ... style can be used with Exceptions as well.

package com.example.mokito3.sujan;

public class AppleService {

    public String saveApple(String apple) {
        String appleString = "i love " + apple + " apple";
        return appleString;
    }
}
package com.example.mokito3.sujan;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.BDDMockito.willThrow;

@ExtendWith(MockitoExtension.class)
public class AppleServiceTest {
    @Mock
    private AppleService appleService;

    @Test
    void saveAppleWithoutMockTest() {
        //given
        willThrow(new IllegalArgumentException()).given(appleService).saveApple(null);
        // when // then
        assertThrows(IllegalArgumentException.class, () -> appleService.saveApple(null));
    }
}
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories { jcenter() }
dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter:5.6.2')
    testCompile 'org.mockito:mockito-junit-jupiter:3.4.4'
}
test {
    useJUnitPlatform()
}

follow us on