blob: cf714e7f81172a998d1ee8a6c3c2cfdd3c3d2573 [file] [log] [blame]
/*
* Copyright (c) 2007 Mockito contributors
* This program is made available under the terms of the MIT License.
*/
package org.mockitousage.stubbing;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.exceptions.verification.TooManyActualInvocations;
import org.mockitoutil.TestBase;
import javax.net.SocketFactory;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.List;
import java.util.Locale;
import static junit.framework.TestCase.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.*;
public class DeepStubbingTest extends TestBase {
static class Person {
Address address;
public Address getAddress() {
return address;
}
public Address getAddress(String addressName) {
return address;
}
public FinalClass getFinalClass() {
return null;
}
}
static class Address {
Street street;
public Street getStreet() {
return street;
}
public Street getStreet(Locale locale) {
return street;
}
}
static class Street {
String name;
public String getName() {
return name;
}
public String getLongName() {
return name;
}
}
static final class FinalClass {}
interface First {
Second getSecond();
String getString();
}
interface Second extends List<String> {}
@Test
public void myTest() throws Exception {
SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf.createSocket(anyString(), eq(80))).thenReturn(null);
sf.createSocket("what", 80);
}
@Test
public void simpleCase() throws Exception {
OutputStream out = new ByteArrayOutputStream();
Socket socket = mock(Socket.class);
when(socket.getOutputStream()).thenReturn(out);
assertSame(out, socket.getOutputStream());
}
/**
* Test that deep stubbing works for one intermediate level
*/
@Test
public void oneLevelDeep() throws Exception {
OutputStream out = new ByteArrayOutputStream();
SocketFactory socketFactory = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(socketFactory.createSocket().getOutputStream()).thenReturn(out);
assertSame(out, socketFactory.createSocket().getOutputStream());
}
/**
* Test that stubbing of two mocks stubs don't interfere
*/
@Test
public void interactions() throws Exception {
OutputStream out1 = new ByteArrayOutputStream();
OutputStream out2 = new ByteArrayOutputStream();
SocketFactory sf1 = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf1.createSocket().getOutputStream()).thenReturn(out1);
SocketFactory sf2 = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf2.createSocket().getOutputStream()).thenReturn(out2);
assertSame(out1, sf1.createSocket().getOutputStream());
assertSame(out2, sf2.createSocket().getOutputStream());
}
/**
* Test that stubbing of methods of different arguments don't interfere
*/
@Test
public void withArguments() throws Exception {
OutputStream out1 = new ByteArrayOutputStream();
OutputStream out2 = new ByteArrayOutputStream();
OutputStream out3 = new ByteArrayOutputStream();
SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf.createSocket().getOutputStream()).thenReturn(out1);
when(sf.createSocket("google.com", 80).getOutputStream()).thenReturn(out2);
when(sf.createSocket("stackoverflow.com", 80).getOutputStream()).thenReturn(out3);
assertSame(out1, sf.createSocket().getOutputStream());
assertSame(out2, sf.createSocket("google.com", 80).getOutputStream());
assertSame(out3, sf.createSocket("stackoverflow.com", 80).getOutputStream());
}
/**
* Test that deep stubbing work with argument patterns
*/
@Test
public void withAnyPatternArguments() throws Exception {
OutputStream out = new ByteArrayOutputStream();
//TODO: should not use javax in case it changes
SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf.createSocket(anyString(), anyInt()).getOutputStream()).thenReturn(out);
assertSame(out, sf.createSocket("google.com", 80).getOutputStream());
assertSame(out, sf.createSocket("stackoverflow.com", 8080).getOutputStream());
}
/**
* Test that deep stubbing work with argument patterns
*/
@Test
public void withComplexPatternArguments() throws Exception {
OutputStream out1 = new ByteArrayOutputStream();
OutputStream out2 = new ByteArrayOutputStream();
SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf.createSocket(anyString(), eq(80)).getOutputStream()).thenReturn(out1);
when(sf.createSocket(anyString(), eq(8080)).getOutputStream()).thenReturn(out2);
assertSame(out2, sf.createSocket("stackoverflow.com", 8080).getOutputStream());
assertSame(out1, sf.createSocket("google.com", 80).getOutputStream());
assertSame(out2, sf.createSocket("google.com", 8080).getOutputStream());
assertSame(out1, sf.createSocket("stackoverflow.com", 80).getOutputStream());
}
/**
* Test that deep stubbing work with primitive expected values
*/
@Test
public void withSimplePrimitive() throws Exception {
int a = 32;
SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf.createSocket().getPort()).thenReturn(a);
assertEquals(a, sf.createSocket().getPort());
}
/**
* Test that deep stubbing work with primitive expected values with
* pattern method arguments
*/
@Test
public void withPatternPrimitive() throws Exception {
int a = 12, b = 23, c = 34;
SocketFactory sf = mock(SocketFactory.class, RETURNS_DEEP_STUBS);
when(sf.createSocket(eq("stackoverflow.com"), eq(80)).getPort()).thenReturn(a);
when(sf.createSocket(eq("google.com"), anyInt()).getPort()).thenReturn(b);
when(sf.createSocket(eq("stackoverflow.com"), eq(8080)).getPort()).thenReturn(c);
assertEquals(b, sf.createSocket("google.com", 80).getPort());
assertEquals(c, sf.createSocket("stackoverflow.com", 8080).getPort());
assertEquals(a, sf.createSocket("stackoverflow.com", 80).getPort());
}
Person person = mock(Person.class, RETURNS_DEEP_STUBS);
@Test
public void shouldStubbingBasicallyWorkFine() throws Exception {
//given
given(person.getAddress().getStreet().getName()).willReturn("Norymberska");
//when
String street = person.getAddress().getStreet().getName();
//then
assertEquals("Norymberska", street);
}
@Test
public void shouldVerificationBasicallyWorkFine() throws Exception {
//given
person.getAddress().getStreet().getName();
//then
verify(person.getAddress().getStreet()).getName();
}
@Test
public void verification_work_with_argument_Matchers_in_nested_calls() throws Exception {
//given
person.getAddress("111 Mock Lane").getStreet();
person.getAddress("111 Mock Lane").getStreet(Locale.ITALIAN).getName();
//then
verify(person.getAddress(anyString())).getStreet();
verify(person.getAddress(anyString()).getStreet(Locale.CHINESE), never()).getName();
verify(person.getAddress(anyString()).getStreet(eq(Locale.ITALIAN))).getName();
}
@Test
public void deep_stub_return_same_mock_instance_if_invocation_matchers_matches() throws Exception {
when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
person.getAddress("the docks").getStreet().getName();
assertSame(person.getAddress("the docks").getStreet(), person.getAddress(anyString()).getStreet());
assertSame(person.getAddress(anyString()).getStreet(), person.getAddress(anyString()).getStreet());
assertSame(person.getAddress("the docks").getStreet(), person.getAddress("the docks").getStreet());
assertSame(person.getAddress(anyString()).getStreet(), person.getAddress("the docks").getStreet());
assertSame(person.getAddress("111 Mock Lane").getStreet(), person.getAddress("the docks").getStreet());
}
@Test
public void times_never_atLeast_atMost_verificationModes_should_work() throws Exception {
when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
person.getAddress("the docks").getStreet().getName();
person.getAddress("the docks").getStreet().getName();
person.getAddress("the docks").getStreet().getName();
person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
verify(person.getAddress("the docks").getStreet(), times(3)).getName();
verify(person.getAddress("the docks").getStreet(Locale.CHINESE), never()).getName();
verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atMost(1)).getName();
}
@Test
public void inOrder_only_work_on_the_very_last_mock_but_it_works() throws Exception {
when(person.getAddress(anyString()).getStreet().getName()).thenReturn("deep");
when(person.getAddress(anyString()).getStreet(Locale.ITALIAN).getName()).thenReturn("deep");
when(person.getAddress(anyString()).getStreet(Locale.CHINESE).getName()).thenReturn("deep");
person.getAddress("the docks").getStreet().getName();
person.getAddress("the docks").getStreet().getLongName();
person.getAddress("the docks").getStreet(Locale.ITALIAN).getName();
person.getAddress("the docks").getStreet(Locale.CHINESE).getName();
InOrder inOrder = inOrder(
person.getAddress("the docks").getStreet(),
person.getAddress("the docks").getStreet(Locale.CHINESE),
person.getAddress("the docks").getStreet(Locale.ITALIAN)
);
inOrder.verify(person.getAddress("the docks").getStreet(), times(1)).getName();
inOrder.verify(person.getAddress("the docks").getStreet()).getLongName();
inOrder.verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atLeast(1)).getName();
inOrder.verify(person.getAddress("the docks").getStreet(Locale.CHINESE)).getName();
}
@Test
public void verificationMode_only_work_on_the_last_returned_mock() throws Exception {
// 1st invocation on Address mock (stubbing)
when(person.getAddress("the docks").getStreet().getName()).thenReturn("deep");
// 2nd invocation on Address mock (real)
person.getAddress("the docks").getStreet().getName();
// 3rd invocation on Address mock (verification)
// (Address mock is not in verification mode)
verify(person.getAddress("the docks").getStreet()).getName();
try {
verify(person.getAddress("the docks"), times(1)).getStreet();
fail();
} catch (TooManyActualInvocations e) {
Assertions.assertThat(e.getMessage())
.contains("Wanted 1 time")
.contains("But was 3 times");
}
}
@Test
public void shouldFailGracefullyWhenClassIsFinal() throws Exception {
//when
FinalClass value = new FinalClass();
given(person.getFinalClass()).willReturn(value);
//then
assertEquals(value, person.getFinalClass());
}
@Test
public void deep_stub_does_not_try_to_mock_generic_final_classes() {
First first = mock(First.class, RETURNS_DEEP_STUBS);
assertNull(first.getString());
assertNull(first.getSecond().get(0));
}
}