• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.adservices.mockito;
18 
19 import static com.android.adservices.mockito.ExtendedMockitoInlineCleanerRule.shouldClearInlineMocksAfterTest;
20 import static com.android.adservices.shared.testing.TestHelper.getAnnotation;
21 
22 import android.util.Log;
23 
24 import com.android.adservices.mockito.ExtendedMockitoInlineCleanerRule.ClearInlineMocksMode;
25 import com.android.adservices.shared.testing.TestHelper;
26 import com.android.modules.utils.testing.AbstractExtendedMockitoRule;
27 import com.android.modules.utils.testing.StaticMockFixture;
28 
29 import com.google.common.collect.ImmutableSet;
30 
31 import org.junit.runner.Description;
32 import org.junit.runners.model.Statement;
33 
34 import java.util.HashSet;
35 import java.util.Set;
36 import java.util.function.Supplier;
37 
38 // TODO(b/338132355): move to shared.common package and rename to just ExtendedMockitoRule
39 
40 // NOTE: javadoc below copied mostly as-is from ExtendedMockitoRule
41 /**
42  * Rule to make it easier to use Extended Mockito:
43  *
44  * <ul>
45  *   <li>Automatically creates and finishes the mock session.
46  *   <li>Provides multiple ways to set which classes must be statically mocked or spied
47  *   <li>Automatically starts mocking (so tests don't need a mockito runner or rule)
48  *   <li>Automatically clears the inlined mocks at the end (to avoid OOM)
49  *   <li>Allows other customization like strictness
50  * </ul>
51  *
52  * <p>Typical usage:
53  *
54  * <pre class="prettyprint">
55  * &#064;Rule
56  * public final AdServicesExtendedMockitoRule extendedMockito =
57  *   new AdServicesExtendedMockitoRule.Builder(this)
58  *     .spyStatic(SomeClassWithStaticMethodsToBeMocked)
59  *     .build();
60  * </pre>
61  */
62 public final class AdServicesExtendedMockitoRule
63         extends AbstractExtendedMockitoRule<
64                 AdServicesExtendedMockitoRule, AdServicesExtendedMockitoRule.Builder>
65         implements StaticClassChecker {
66 
67     private static final String TAG = AdServicesExtendedMockitoRule.class.getSimpleName();
68 
69     private final Set<Class<?>> mSpiedOrMockedStaticClasses = new HashSet<>();
70 
71     private String mTestName = DEFAULT_TEST_NAME;
72 
AdServicesExtendedMockitoRule(Builder builder)73     public AdServicesExtendedMockitoRule(Builder builder) {
74         super(builder);
75     }
76 
77     @SafeVarargs
AdServicesExtendedMockitoRule(Supplier<? extends StaticMockFixture>.... suppliers)78     public AdServicesExtendedMockitoRule(Supplier<? extends StaticMockFixture>... suppliers) {
79         super(new Builder().addStaticMockFixtures(suppliers));
80     }
81 
82     @Override
getTestName()83     public final String getTestName() {
84         return mTestName;
85     }
86 
87     // Overridden to get test name
88     @Override
apply(Statement base, Description description)89     public final Statement apply(Statement base, Description description) {
90         Statement realStatement = super.apply(base, description);
91         return new Statement() {
92 
93             @Override
94             public void evaluate() throws Throwable {
95                 mTestName = TestHelper.getTestName(description);
96                 try {
97                     realStatement.evaluate();
98                 } finally {
99                     mTestName = DEFAULT_TEST_NAME;
100                 }
101             }
102         };
103     }
104 
105     @Override
106     protected final Set<Class<?>> getSpiedStaticClasses(Description description) {
107         Set<Class<?>> spiedStaticClasses = super.getSpiedStaticClasses(description);
108         mSpiedOrMockedStaticClasses.addAll(spiedStaticClasses);
109         return spiedStaticClasses;
110     }
111 
112     @Override
113     protected final Set<Class<?>> getMockedStaticClasses(Description description) {
114         Set<Class<?>> mockedStaticClasses = super.getMockedStaticClasses(description);
115         mSpiedOrMockedStaticClasses.addAll(mockedStaticClasses);
116         return mockedStaticClasses;
117     }
118 
119     @Override
120     protected final boolean getClearInlineMethodsAtTheEnd(Description description) {
121         ClearInlineMocksMode annotation = getAnnotation(description, ClearInlineMocksMode.class);
122         if (annotation != null) {
123             boolean shouldClear = shouldClearInlineMocksAfterTest(description, annotation.value());
124             Log.d(
125                     TAG,
126                     "getClearInlineMethodsAtTheEnd(): returning value based on annotation ("
127                             + shouldClear
128                             + ") for "
129                             + TestHelper.getTestName(description));
130             return shouldClear;
131         }
132         return super.getClearInlineMethodsAtTheEnd(description);
133     }
134 
135     @Override
136     public ImmutableSet<Class<?>> getSpiedOrMockedClasses() {
137         return ImmutableSet.copyOf(mSpiedOrMockedStaticClasses);
138     }
139 
140     @Override
141     public boolean isSpiedOrMocked(Class<?> clazz) {
142         return mSpiedOrMockedStaticClasses.contains(clazz);
143     }
144 
145     @Override
146     public String toString() {
147         return "["
148                 + getClass().getSimpleName()
149                 + ": spying / mocking on "
150                 + mSpiedOrMockedStaticClasses.size()
151                 + " classes: "
152                 + mSpiedOrMockedStaticClasses
153                 + "]";
154     }
155 
156     public static final class Builder
157             extends AbstractBuilder<AdServicesExtendedMockitoRule, Builder> {
158 
159         public Builder() {
160             super();
161         }
162 
163         public Builder(Object testClassInstance) {
164             super(testClassInstance);
165         }
166 
167         @Override
168         public AdServicesExtendedMockitoRule build() {
169             return new AdServicesExtendedMockitoRule(this);
170         }
171     }
172 }
173