mirror of
https://github.com/google/nomulus.git
synced 2025-06-28 07:13:34 +02:00
mv com/google/domain/registry google/registry
This change renames directories in preparation for the great package rename. The repository is now in a broken state because the code itself hasn't been updated. However this should ensure that git correctly preserves history for each file.
This commit is contained in:
parent
a41677aea1
commit
5012893c1d
2396 changed files with 0 additions and 0 deletions
174
javatests/google/registry/testing/InjectRule.java
Normal file
174
javatests/google/registry/testing/InjectRule.java
Normal file
|
@ -0,0 +1,174 @@
|
|||
// Copyright 2016 The Domain Registry Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.domain.registry.testing;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import org.junit.rules.ExternalResource;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* JUnit Rule for overriding {@code private static} fields during a test.
|
||||
*
|
||||
* <p>This rule uses reflection to change the value of a field while your test
|
||||
* is running and then restore it to its original value after it's done (even
|
||||
* if the test fails). The injection will work even if the field is marked
|
||||
* {@code private} (but not if it's {@code final}). The downside is that if you
|
||||
* rename the field in the future, Eclipse refactoring won't be smart enough to
|
||||
* update the injection site.
|
||||
*
|
||||
* <p>We encourage you to consider using
|
||||
* {@link com.google.domain.registry.util.NonFinalForTesting @NonFinalForTesting}
|
||||
* to document your injected fields.
|
||||
*
|
||||
* <p>This class is a horrible evil hack, but it alleviates you of the toil of
|
||||
* having to break encapsulation by making your fields non-{@code private}, using
|
||||
* the {@link com.google.common.annotations.VisibleForTesting @VisibleForTesting}
|
||||
* annotation to document why you've reduced visibility, creating a temporary field
|
||||
* to store the old value, and then writing an {@link org.junit.After @After}
|
||||
* method to restore it. So sometimes it feels good to be evil; but hopefully one
|
||||
* day we'll be able to delete this class and do things <i>properly</i> with
|
||||
* <a href="http://square.github.io/dagger/">Dagger</a> dependency injection.
|
||||
*
|
||||
* <p>You use this class by declaring it as a {@link org.junit.Rule @Rule}
|
||||
* field and then calling {@link #setStaticField} from either your {@link
|
||||
* org.junit.Test @Test} or {@link org.junit.Before @Before} methods. For
|
||||
* example:
|
||||
*
|
||||
* <pre>
|
||||
* // Doomsday.java
|
||||
* public class Doomsday {
|
||||
*
|
||||
* private static Clock clock = new SystemClock();
|
||||
*
|
||||
* public long getTime() {
|
||||
* return clock.currentTimeMillis();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // DoomsdayTest.java
|
||||
* @RunWith(JUnit4.class)
|
||||
* public class DoomsdayTest {
|
||||
*
|
||||
* @Rule
|
||||
* public InjectRule inject = new InjectRule();
|
||||
*
|
||||
* private final FakeClock clock = new FakeClock();
|
||||
*
|
||||
* @Before
|
||||
* public void before() {
|
||||
* inject.setStaticField(Doomsday.class, "clock", clock);
|
||||
* }
|
||||
*
|
||||
* @Test
|
||||
* public void test() {
|
||||
* clock.advanceBy(666L);
|
||||
* Doomsday doom = new Doomsday();
|
||||
* assertEquals(666L, doom.getTime());
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see com.google.domain.registry.util.NonFinalForTesting
|
||||
* @see org.junit.rules.ExternalResource
|
||||
*/
|
||||
public class InjectRule extends ExternalResource {
|
||||
|
||||
private static class Change {
|
||||
private final Field field;
|
||||
@Nullable private final Object oldValue;
|
||||
@Nullable private final Object newValue;
|
||||
|
||||
Change(Field field, @Nullable Object oldValue, @Nullable Object newValue) {
|
||||
this.field = field;
|
||||
this.oldValue = oldValue;
|
||||
this.newValue = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
private final List<Change> changes = new ArrayList<>();
|
||||
private final Set<Field> injected = new HashSet<>();
|
||||
|
||||
/**
|
||||
* Sets a static field and be restores its current value after the test completes.
|
||||
*
|
||||
* <p>The field is allowed to be {@code private}, but it most not be {@code final}.
|
||||
*
|
||||
* <p>This method may be called either from either your {@link org.junit.Before @Before}
|
||||
* method or from the {@link org.junit.Test @Test} method itself. However you may not
|
||||
* inject the same field multiple times during the same test.
|
||||
*
|
||||
* @throws IllegalArgumentException if the static field could not be found or modified.
|
||||
* @throws IllegalStateException if the field has already been injected during this test.
|
||||
*/
|
||||
public void setStaticField(Class<?> clazz, String fieldName, @Nullable Object newValue) {
|
||||
Field field;
|
||||
Object oldValue;
|
||||
try {
|
||||
field = clazz.getDeclaredField(fieldName);
|
||||
field.setAccessible(true);
|
||||
oldValue = field.get(null);
|
||||
} catch (NoSuchFieldException
|
||||
| SecurityException
|
||||
| IllegalArgumentException
|
||||
| IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Static field not found: %s.%s", clazz.getSimpleName(), fieldName), e);
|
||||
}
|
||||
checkState(!injected.contains(field),
|
||||
"Static field already injected: %s.%s", clazz.getSimpleName(), fieldName);
|
||||
try {
|
||||
field.set(null, newValue);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Static field not settable: %s.%s", clazz.getSimpleName(), fieldName), e);
|
||||
}
|
||||
changes.add(new Change(field, oldValue, newValue));
|
||||
injected.add(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
RuntimeException thrown = null;
|
||||
for (Change change : changes) {
|
||||
try {
|
||||
checkState(change.field.get(null).equals(change.newValue),
|
||||
"Static field value was changed post-injection: %s.%s",
|
||||
change.field.getDeclaringClass().getSimpleName(), change.field.getName());
|
||||
change.field.set(null, change.oldValue);
|
||||
} catch (IllegalArgumentException
|
||||
| IllegalStateException
|
||||
| IllegalAccessException e) {
|
||||
if (thrown == null) {
|
||||
thrown = new RuntimeException(e);
|
||||
} else {
|
||||
thrown.addSuppressed(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
changes.clear();
|
||||
injected.clear();
|
||||
if (thrown != null) {
|
||||
throw thrown;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue