From 528226a4177cc4809f764114bcf2e785069aa425 Mon Sep 17 00:00:00 2001 From: Krichevskaya Date: Wed, 31 Mar 2021 02:38:11 +0700 Subject: [PATCH 1/4] verify --- .../java/ru/nsu/sd/MockBuddy/MockBuddy.java | 10 ++++ .../sd/MockBuddy/internal/MockBuddyCore.java | 4 ++ .../internal/creation/ByteBuddyMockMaker.java | 5 +- .../internal/handling/InvocationHolder.java | 53 +++++++++++++++++ .../handling/MockInvocationHandler.java | 57 ++++++++++++++++++- .../handling/VerificationHandler.java | 4 ++ .../java/ru/nsu/sd/MockBuddy/VerifyTest.java | 51 +++++++++++++++++ 7 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 src/main/java/ru/nsu/sd/MockBuddy/internal/handling/InvocationHolder.java create mode 100644 src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java create mode 100644 src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java diff --git a/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java b/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java index 98398ce..a7ee92a 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java @@ -1,6 +1,7 @@ package ru.nsu.sd.MockBuddy; import ru.nsu.sd.MockBuddy.internal.MockBuddyCore; +import ru.nsu.sd.MockBuddy.internal.MockingInfo; import ru.nsu.sd.MockBuddy.internal.stubbing.Stubber; public class MockBuddy { @@ -26,4 +27,13 @@ public static T spy(Class clazz) { public static Stubber when(T obj) { return mockBuddyCore.when(obj); } + +// public static T verify(T obj, Integer times) { +// return mockBuddyCore.verify(obj, times); +// } + + public static int temporaryVerify() { + return MockingInfo.getLastMockInvocationHandler().getInvocationCounter(); + } + } diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java index dd3a5b7..cfd2014 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java @@ -21,4 +21,8 @@ public T spy(T obj) { public Stubber when(T obj) { return new Stubber<>(); } + +// public T verify(T obj, Integer times) { +// return ByteBuddyMockMaker.verify(obj, times, MockingInfo.getLastMockInvocationHandler()); +// } } diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java index ef13506..c932360 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java @@ -94,5 +94,8 @@ public static T spy(T obj, MockInvocationHandler mockInvocationHandler) { return instance; } -} +// public static T verify(T obj, Integer times, MockInvocationHandler mockInvocationHandler) { +// return null; +// } +} diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/InvocationHolder.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/InvocationHolder.java new file mode 100644 index 0000000..8b0b015 --- /dev/null +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/InvocationHolder.java @@ -0,0 +1,53 @@ +package ru.nsu.sd.MockBuddy.internal.handling; + +import java.lang.reflect.Method; +import java.util.Arrays; + +public class InvocationHolder { + + private final Object[] args; + private final Method method; + + private int invocationCounter = 0; + + InvocationHolder(Method method, Object[] args) { + this.args = args; + this.method = method; + } + + public Object[] getArgs() { + return args; + } + + public Method getMethod() { + return method; + } + + + public int getInvocationCounter() { + return invocationCounter; + } + + public void increaseCounter() { + invocationCounter++; + +// System.out.println(this.toString() + " counter: " + invocationCounter); + } + + public void decreaseCounter() { + if (invocationCounter > 0) { + invocationCounter--; + } + +// System.out.println(this.toString() + " counter: " + invocationCounter); + + } + + @Override + public String toString() { + return "DataHolder{" + + "args=" + Arrays.toString(args) + + ", method=" + method + + '}'; + } +} diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java index e763e01..3cb0969 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.concurrent.Callable; /** @@ -21,6 +22,8 @@ public class MockInvocationHandler { private final List dataHolders = new ArrayList<>(); + private final List invocationHolders = new ArrayList<>(); + private Method lastMethod = null; private Object[] lastArgs = null; private final DelegationStrategy delegationStrategy; @@ -48,18 +51,34 @@ public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllAr lastArgs = args; } + for (InvocationHolder invocationHolder : invocationHolders) { + if (invocationHolder.getMethod().equals(method) && Arrays.deepEquals(invocationHolder.getArgs(), args)) { + invocationHolder.increaseCounter(); + } + } + + if (invocationHolders.stream().noneMatch(x -> x.getMethod().equals(method) && Arrays.deepEquals(x.getArgs(), args))) { + InvocationHolder holder = new InvocationHolder(method, args); + holder.increaseCounter(); + invocationHolders.add(holder); + } + + // checks if the method was already called with the given arguments (without argument matchers) for (DataHolder dataHolder : dataHolders) { if (dataHolder.getMethod().equals(method) && Arrays.deepEquals(dataHolder.getArgs(), args)) { if (!dataHolder.isWithMatchers()) { switch (dataHolder.getDelegationStrategy()) { case CALL_REAL_METHOD: +// System.out.println("first call real method"); return zuper.call(); case THROW_EXCEPTION: +// System.out.println("first throw exception"); throw dataHolder.getToThrow(); case RETURN_CUSTOM: +// System.out.println("first return custom"); return dataHolder.getRetObj(); } @@ -78,8 +97,10 @@ public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllAr match = dataHolder.getLocalArgumentMatchersList().get(i).matches(lastArgs[i]); if (!match) { - if (delegationStrategy == DelegationStrategy.CALL_REAL_METHOD) + if (delegationStrategy == DelegationStrategy.CALL_REAL_METHOD) { +// System.out.println("let's try here when"); return zuper.call(); + } else return null; } @@ -87,18 +108,22 @@ public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllAr switch (dataHolder.getDelegationStrategy()) { case CALL_REAL_METHOD: +// System.out.println("second call real method"); return zuper.call(); case THROW_EXCEPTION: +// System.out.println("second throw exception"); throw dataHolder.getToThrow(); case RETURN_CUSTOM: +// System.out.println("second return custom"); return dataHolder.getRetObj(); } } else { // Override matcher +// System.out.println("xz what is this"); return null; } } @@ -114,6 +139,13 @@ public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllAr public void setRetObj(Object retObj) { + // Decrease invocation counter because method was in MockBuddy.when + for (InvocationHolder invocationHolder : invocationHolders) { + if (invocationHolder.getMethod().equals(lastMethod) && Arrays.deepEquals(invocationHolder.getArgs(), lastArgs)) { + invocationHolder.decreaseCounter(); + } + } + // Remove existing rule with same method and arguments dataHolders.removeIf(dh -> dh.getMethod().equals(lastMethod) && Arrays.deepEquals(dh.getArgs(), lastArgs)); @@ -136,6 +168,13 @@ public void setRetObj(Object retObj) { public void setThrowable(Throwable throwable) { + // Decrease invocation counter because method was in MockBuddy.when + for (InvocationHolder invocationHolder : invocationHolders) { + if (invocationHolder.getMethod().equals(lastMethod) && Arrays.deepEquals(invocationHolder.getArgs(), lastArgs)) { + invocationHolder.decreaseCounter(); + } + } + // Remove existing rule with same method and arguments dataHolders.removeIf(dh -> dh.getMethod().equals(lastMethod) && Arrays.deepEquals(dh.getArgs(), lastArgs)); @@ -158,6 +197,13 @@ public void setThrowable(Throwable throwable) { public void setRealMethodInvocation() { + // Decrease invocation counter because method was in MockBuddy.when + for (InvocationHolder invocationHolder : invocationHolders) { + if (invocationHolder.getMethod().equals(lastMethod) && Arrays.deepEquals(invocationHolder.getArgs(), lastArgs)) { + invocationHolder.decreaseCounter(); + } + } + // Remove existing rule with same method and arguments dataHolders.removeIf(dh -> dh.getMethod().equals(lastMethod) && Arrays.deepEquals(dh.getArgs(), lastArgs)); @@ -177,4 +223,13 @@ public void setRealMethodInvocation() { dataHolders.add(new DataHolder(lastMethod, lastArgs)); } } + + public int getInvocationCounter() { + + if (invocationHolders.stream().noneMatch(x -> x.getMethod().equals(lastMethod) && Arrays.deepEquals(x.getArgs(), lastArgs))) { + return 0; + } else { + return Objects.requireNonNull(invocationHolders.stream().filter(x -> x.getMethod().equals(lastMethod) && Arrays.deepEquals(x.getArgs(), lastArgs)).findFirst().orElse(null)).getInvocationCounter(); + } + } } diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java new file mode 100644 index 0000000..a150ae8 --- /dev/null +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java @@ -0,0 +1,4 @@ +package ru.nsu.sd.MockBuddy.internal.handling; + +public class VerificationHandler { +} diff --git a/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java new file mode 100644 index 0000000..5da7a10 --- /dev/null +++ b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java @@ -0,0 +1,51 @@ +package ru.nsu.sd.MockBuddy; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import ru.nsu.sd.MockBuddy.testclasses.TestClass; + +import static ru.nsu.sd.MockBuddy.internal.matching.ArgumentMatchers.*; + +public class VerifyTest { + + private TestClass testClass; + + @Before + public void setup() { + testClass = MockBuddy.mock(TestClass.class); + } + + @Test + public void test_1() { + // 123 || 333 + MockBuddy.when(testClass.bar(123, 3)).thenReturn(11); + + Assert.assertEquals(0, MockBuddy.temporaryVerify()); + + System.out.println(testClass.bar(123, 3)); + System.out.println(testClass.bar(123, 3)); + + Assert.assertEquals(2, MockBuddy.temporaryVerify()); + + MockBuddy.when(testClass.bar(123, 3)).thenReturn(12); + + Assert.assertEquals(2, MockBuddy.temporaryVerify()); + + System.out.println(testClass.bar(123, 3)); + + Assert.assertEquals(3, MockBuddy.temporaryVerify()); + + System.out.println(testClass.bar(123, 4)); + + Assert.assertEquals(1, MockBuddy.temporaryVerify()); + + System.out.println(testClass.bar(0, 0)); + + Assert.assertEquals(1, MockBuddy.temporaryVerify()); + +// MockBuddy.verify(testClass, 3).bar(123, 3); + + + } +} From 93b9c103fce5e2c0571ed37f8704e0914c284c2e Mon Sep 17 00:00:00 2001 From: Krichevskaya Date: Wed, 31 Mar 2021 10:11:55 +0700 Subject: [PATCH 2/4] verify done --- .../java/ru/nsu/sd/MockBuddy/MockBuddy.java | 6 +-- .../sd/MockBuddy/internal/MockBuddyCore.java | 7 +-- .../sd/MockBuddy/internal/MockingInfo.java | 38 +++++++++++++++ .../internal/creation/ByteBuddyMockMaker.java | 23 ++++++++-- .../handling/MockInvocationHandler.java | 46 ++++++++++++++++--- .../handling/VerificationHandler.java | 38 +++++++++++++++ .../java/ru/nsu/sd/MockBuddy/VerifyTest.java | 40 +++++++++++----- 7 files changed, 171 insertions(+), 27 deletions(-) diff --git a/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java b/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java index a7ee92a..9fd3b2f 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java @@ -28,9 +28,9 @@ public static Stubber when(T obj) { return mockBuddyCore.when(obj); } -// public static T verify(T obj, Integer times) { -// return mockBuddyCore.verify(obj, times); -// } + public static T verify(T obj, Integer times) { + return mockBuddyCore.verify(obj, times); + } public static int temporaryVerify() { return MockingInfo.getLastMockInvocationHandler().getInvocationCounter(); diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java index cfd2014..1da7886 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/MockBuddyCore.java @@ -2,6 +2,7 @@ import ru.nsu.sd.MockBuddy.internal.creation.ByteBuddyMockMaker; import ru.nsu.sd.MockBuddy.internal.handling.DelegationStrategy; +import ru.nsu.sd.MockBuddy.internal.handling.VerificationHandler; import ru.nsu.sd.MockBuddy.internal.stubbing.Stubber; public class MockBuddyCore { @@ -22,7 +23,7 @@ public Stubber when(T obj) { return new Stubber<>(); } -// public T verify(T obj, Integer times) { -// return ByteBuddyMockMaker.verify(obj, times, MockingInfo.getLastMockInvocationHandler()); -// } + public T verify(T obj, Integer times) { + return ByteBuddyMockMaker.verify(obj, times); + } } diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/MockingInfo.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/MockingInfo.java index 1cc80ad..d1cc122 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/MockingInfo.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/MockingInfo.java @@ -1,15 +1,24 @@ package ru.nsu.sd.MockBuddy.internal; +import ru.nsu.sd.MockBuddy.internal.handling.InvocationHolder; import ru.nsu.sd.MockBuddy.internal.handling.MockInvocationHandler; import ru.nsu.sd.MockBuddy.internal.matching.ArgumentMatcherStorage; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + public class MockingInfo { private static final ArgumentMatcherStorage argumentMatcherStorage; private static MockInvocationHandler lastMockInvocationHandler; + private static HashMap> hashMap; + static { argumentMatcherStorage = new ArgumentMatcherStorage(); + hashMap = new HashMap<>(); } public static MockInvocationHandler getLastMockInvocationHandler() { @@ -23,4 +32,33 @@ public static void setLastMockInvocationHandler(MockInvocationHandler handler) { public static ArgumentMatcherStorage getArgumentMatcherStorage() { return argumentMatcherStorage; } + + public static void addObjectToHashMup(Object obj, InvocationHolder holder) { + + if (hashMap.containsKey(System.identityHashCode(obj))) { + + if (hashMap.get(System.identityHashCode(obj)).stream().noneMatch(x -> x.getMethod().equals(holder.getMethod()) && Arrays.deepEquals(x.getArgs(), holder.getArgs()))) { + List newHolders = hashMap.get(System.identityHashCode(obj)); + newHolders.add(holder); + hashMap.put(System.identityHashCode(obj), newHolders); + } else { + List newHolders = hashMap.get(System.identityHashCode(obj)); + newHolders.add(holder); + hashMap.put(System.identityHashCode(obj), newHolders); + } + + } else { + List newHolders = new ArrayList<>(); + newHolders.add(holder); + hashMap.put(System.identityHashCode(obj), newHolders); + } + } + + public static void addHolders(Object obj, List holders) { + hashMap.put(System.identityHashCode(obj), holders); + } + + public static List getListOfHolders(Object obj) { + return hashMap.get(System.identityHashCode(obj)); + } } diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java index c932360..767f9da 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/creation/ByteBuddyMockMaker.java @@ -8,7 +8,9 @@ import org.objenesis.instantiator.ObjectInstantiator; import ru.nsu.sd.MockBuddy.internal.MockingInfo; import ru.nsu.sd.MockBuddy.internal.handling.DelegationStrategy; +import ru.nsu.sd.MockBuddy.internal.handling.InvocationHolder; import ru.nsu.sd.MockBuddy.internal.handling.MockInvocationHandler; +import ru.nsu.sd.MockBuddy.internal.handling.VerificationHandler; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -95,7 +97,22 @@ public static T spy(T obj, MockInvocationHandler mockInvocationHandler) { } -// public static T verify(T obj, Integer times, MockInvocationHandler mockInvocationHandler) { -// return null; -// } + public static T verify(T obj, Integer times) { + + VerificationHandler verificationHandler = new VerificationHandler(obj, times); + + @SuppressWarnings("unchecked") + Class byteBuddy = new ByteBuddy() + .subclass((Class) obj.getClass().getSuperclass()) + .method(ElementMatchers.any()) + .intercept(MethodDelegation.to(verificationHandler)) + .make() + .load(ClassLoader.getSystemClassLoader()) + .getLoaded(); + + // Create object without calling constructor + Objenesis objenesis = new ObjenesisStd(); + ObjectInstantiator thingyInstantiator = objenesis.getInstantiatorOf(byteBuddy); + return (T) thingyInstantiator.newInstance(); + } } diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java index 3cb0969..dea69de 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/MockInvocationHandler.java @@ -1,9 +1,6 @@ package ru.nsu.sd.MockBuddy.internal.handling; -import net.bytebuddy.implementation.bind.annotation.AllArguments; -import net.bytebuddy.implementation.bind.annotation.Origin; -import net.bytebuddy.implementation.bind.annotation.RuntimeType; -import net.bytebuddy.implementation.bind.annotation.SuperCall; +import net.bytebuddy.implementation.bind.annotation.*; import ru.nsu.sd.MockBuddy.internal.MockingInfo; import ru.nsu.sd.MockBuddy.internal.matching.matchers.ArgumentMatcher; @@ -22,18 +19,28 @@ public class MockInvocationHandler { private final List dataHolders = new ArrayList<>(); - private final List invocationHolders = new ArrayList<>(); + private List invocationHolders = new ArrayList<>(); private Method lastMethod = null; private Object[] lastArgs = null; private final DelegationStrategy delegationStrategy; + private Object obj = null; + public MockInvocationHandler(DelegationStrategy delegationStrategy) { this.delegationStrategy = delegationStrategy; } @RuntimeType - public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllArguments Object[] args) throws Throwable { + public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllArguments Object[] args, @This Object obj) throws Throwable { + + this.obj = obj; + + invocationHolders = MockingInfo.getListOfHolders(obj); + + if (invocationHolders == null) { + invocationHolders = new ArrayList(); + } MockingInfo.setLastMockInvocationHandler(this); @@ -63,6 +70,7 @@ public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllAr invocationHolders.add(holder); } + MockingInfo.addHolders(obj, invocationHolders); // checks if the method was already called with the given arguments (without argument matchers) for (DataHolder dataHolder : dataHolders) { @@ -139,6 +147,12 @@ public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllAr public void setRetObj(Object retObj) { + invocationHolders = MockingInfo.getListOfHolders(obj); + + if (invocationHolders == null) { + invocationHolders = new ArrayList(); + } + // Decrease invocation counter because method was in MockBuddy.when for (InvocationHolder invocationHolder : invocationHolders) { if (invocationHolder.getMethod().equals(lastMethod) && Arrays.deepEquals(invocationHolder.getArgs(), lastArgs)) { @@ -146,6 +160,8 @@ public void setRetObj(Object retObj) { } } + MockingInfo.addHolders(obj, invocationHolders); + // Remove existing rule with same method and arguments dataHolders.removeIf(dh -> dh.getMethod().equals(lastMethod) && Arrays.deepEquals(dh.getArgs(), lastArgs)); @@ -168,6 +184,12 @@ public void setRetObj(Object retObj) { public void setThrowable(Throwable throwable) { + invocationHolders = MockingInfo.getListOfHolders(obj); + + if (invocationHolders == null) { + invocationHolders = new ArrayList(); + } + // Decrease invocation counter because method was in MockBuddy.when for (InvocationHolder invocationHolder : invocationHolders) { if (invocationHolder.getMethod().equals(lastMethod) && Arrays.deepEquals(invocationHolder.getArgs(), lastArgs)) { @@ -175,6 +197,8 @@ public void setThrowable(Throwable throwable) { } } + MockingInfo.addHolders(obj, invocationHolders); + // Remove existing rule with same method and arguments dataHolders.removeIf(dh -> dh.getMethod().equals(lastMethod) && Arrays.deepEquals(dh.getArgs(), lastArgs)); @@ -197,6 +221,12 @@ public void setThrowable(Throwable throwable) { public void setRealMethodInvocation() { + invocationHolders = MockingInfo.getListOfHolders(obj); + + if (invocationHolders == null) { + invocationHolders = new ArrayList(); + } + // Decrease invocation counter because method was in MockBuddy.when for (InvocationHolder invocationHolder : invocationHolders) { if (invocationHolder.getMethod().equals(lastMethod) && Arrays.deepEquals(invocationHolder.getArgs(), lastArgs)) { @@ -204,6 +234,8 @@ public void setRealMethodInvocation() { } } + MockingInfo.addHolders(obj, invocationHolders); + // Remove existing rule with same method and arguments dataHolders.removeIf(dh -> dh.getMethod().equals(lastMethod) && Arrays.deepEquals(dh.getArgs(), lastArgs)); @@ -226,6 +258,8 @@ public void setRealMethodInvocation() { public int getInvocationCounter() { + invocationHolders = MockingInfo.getListOfHolders(obj); + if (invocationHolders.stream().noneMatch(x -> x.getMethod().equals(lastMethod) && Arrays.deepEquals(x.getArgs(), lastArgs))) { return 0; } else { diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java index a150ae8..9cfdd99 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/handling/VerificationHandler.java @@ -1,4 +1,42 @@ package ru.nsu.sd.MockBuddy.internal.handling; +import net.bytebuddy.implementation.bind.annotation.AllArguments; +import net.bytebuddy.implementation.bind.annotation.Origin; +import net.bytebuddy.implementation.bind.annotation.RuntimeType; +import net.bytebuddy.implementation.bind.annotation.SuperCall; +import ru.nsu.sd.MockBuddy.internal.MockingInfo; +import ru.nsu.sd.MockBuddy.internal.matching.matchers.ArgumentMatcher; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Callable; + + public class VerificationHandler { + + private Integer times; + private Object obj; + + public VerificationHandler(Object obj, Integer times) { + this.obj = obj; + this.times = times; + } + + @RuntimeType + public Object invoke(@SuperCall Callable zuper, @Origin Method method, @AllArguments Object[] args) throws Throwable { + + if (Objects.requireNonNull(MockingInfo.getListOfHolders(obj) + .stream() + .filter(x -> x.getMethod().equals(method) && Arrays.deepEquals(x.getArgs(), args)) + .findFirst().orElse(null)) + .getInvocationCounter() != times) { + throw new IllegalArgumentException("Verification error"); + } + + return null; + + } } diff --git a/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java index 5da7a10..635ff07 100644 --- a/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java +++ b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java @@ -10,42 +10,58 @@ public class VerifyTest { private TestClass testClass; + private TestClass testClass2; @Before public void setup() { testClass = MockBuddy.mock(TestClass.class); + testClass2 = MockBuddy.mock(TestClass.class); } @Test public void test_1() { + // 123 || 333 MockBuddy.when(testClass.bar(123, 3)).thenReturn(11); + MockBuddy.when(testClass2.bar(7, 3)).thenReturn(17); - Assert.assertEquals(0, MockBuddy.temporaryVerify()); + MockBuddy.verify(testClass, 0).bar(123, 3); + MockBuddy.verify(testClass2, 0).bar(7, 3); - System.out.println(testClass.bar(123, 3)); - System.out.println(testClass.bar(123, 3)); + testClass.bar(123, 3); // 1 + testClass.bar(123, 3); // 2 - Assert.assertEquals(2, MockBuddy.temporaryVerify()); + MockBuddy.verify(testClass, 2).bar(123, 3); MockBuddy.when(testClass.bar(123, 3)).thenReturn(12); - Assert.assertEquals(2, MockBuddy.temporaryVerify()); + MockBuddy.verify(testClass, 2).bar(123, 3); + + testClass.bar(123, 3); // 3 + + MockBuddy.verify(testClass, 3).bar(123, 3); + + testClass.bar(123, 4); // 1 - System.out.println(testClass.bar(123, 3)); + MockBuddy.verify(testClass, 1).bar(123, 4); - Assert.assertEquals(3, MockBuddy.temporaryVerify()); + testClass.bar(0, 0); // 1 - System.out.println(testClass.bar(123, 4)); + MockBuddy.verify(testClass, 1).bar(0, 0); + MockBuddy.verify(testClass, 3).bar(123, 3); - Assert.assertEquals(1, MockBuddy.temporaryVerify()); - System.out.println(testClass.bar(0, 0)); + } - Assert.assertEquals(1, MockBuddy.temporaryVerify()); + @Test + public void test_2() { -// MockBuddy.verify(testClass, 3).bar(123, 3); + // 123 || 333 + MockBuddy.when(testClass.bar(123, 3)).thenReturn(11); + MockBuddy.when(testClass2.bar(7, 3)).thenReturn(17); + MockBuddy.verify(testClass, 0).bar(123, 3); + MockBuddy.verify(testClass2, 0).bar(7, 3); } } From 3eb04e9df03968196831c51c02a93eddd6a4928f Mon Sep 17 00:00:00 2001 From: Krichevskaya Date: Wed, 31 Mar 2021 10:17:26 +0700 Subject: [PATCH 3/4] verify done --- src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java | 4 ---- src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java | 12 ------------ 2 files changed, 16 deletions(-) diff --git a/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java b/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java index 9fd3b2f..56ea627 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/MockBuddy.java @@ -32,8 +32,4 @@ public static T verify(T obj, Integer times) { return mockBuddyCore.verify(obj, times); } - public static int temporaryVerify() { - return MockingInfo.getLastMockInvocationHandler().getInvocationCounter(); - } - } diff --git a/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java index 635ff07..c78d9b0 100644 --- a/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java +++ b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java @@ -52,16 +52,4 @@ public void test_1() { } - - @Test - public void test_2() { - - // 123 || 333 - MockBuddy.when(testClass.bar(123, 3)).thenReturn(11); - MockBuddy.when(testClass2.bar(7, 3)).thenReturn(17); - - MockBuddy.verify(testClass, 0).bar(123, 3); - MockBuddy.verify(testClass2, 0).bar(7, 3); - - } } From 145f914b34762b00bdb3c0bac00970beeb8f8a59 Mon Sep 17 00:00:00 2001 From: Krichevskaya Date: Wed, 31 Mar 2021 10:21:20 +0700 Subject: [PATCH 4/4] bug fix --- .../ru/nsu/sd/MockBuddy/internal/annotations/Mock.java | 7 ------- .../ru/nsu/sd/MockBuddy/internal/annotations/Spy.java | 8 -------- src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java | 5 ++++- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Mock.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Mock.java index f748601..516682f 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Mock.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Mock.java @@ -14,13 +14,6 @@ * Minimizes repetitive mock creation code. * Makes the test class more readable. * - * Example: - *

- *
- *
- *
- * 
- * */ @Target(FIELD) @Retention(RUNTIME) diff --git a/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Spy.java b/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Spy.java index da4602c..e973a57 100644 --- a/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Spy.java +++ b/src/main/java/ru/nsu/sd/MockBuddy/internal/annotations/Spy.java @@ -8,14 +8,6 @@ /** * Allows shorthand wrapping of field instances in an spy object. - * - * Example: - *

- *
- *
- *
- * 
- * */ @Target(FIELD) @Retention(RUNTIME) diff --git a/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java index c78d9b0..ac04869 100644 --- a/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java +++ b/src/test/java/ru/nsu/sd/MockBuddy/VerifyTest.java @@ -3,18 +3,21 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import ru.nsu.sd.MockBuddy.internal.annotations.Mock; +import ru.nsu.sd.MockBuddy.internal.annotations.MockInitializer; import ru.nsu.sd.MockBuddy.testclasses.TestClass; import static ru.nsu.sd.MockBuddy.internal.matching.ArgumentMatchers.*; public class VerifyTest { + @Mock private TestClass testClass; private TestClass testClass2; @Before public void setup() { - testClass = MockBuddy.mock(TestClass.class); + MockInitializer.initMocks(this); testClass2 = MockBuddy.mock(TestClass.class); }