Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ Predefine Switchers result outside your test methods via Parameterized Test.
</br>It encapsulates the test and makes sure that the Switcher returns to its original state after concluding the test.

```java
@ParameterizedTest
@SwitcherMock(key = MY_SWITCHER, result = true)
void testMyFeature() {
assertTrue(instance.myFeature());
Expand Down
16 changes: 10 additions & 6 deletions src/main/java/com/github/switcherapi/client/SwitcherMock.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.lang.annotation.Target;

import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;

/**
Expand All @@ -18,12 +19,15 @@
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ArgumentsSource(SwitcherMockRunner.class)
@ExtendWith(SwitcherMockRunner.class)
@ArgumentsSource(SwitcherMockExtension.class)
@ExtendWith(SwitcherMockExtension.class)
@ParameterizedTest
public @interface SwitcherMock {

String key();

boolean result();

String key() default "";

boolean result() default true;

SwitcherMockValue[] switchers() default {};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.github.switcherapi.client;

import org.apache.commons.lang3.ArrayUtils;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.support.AnnotationConsumer;

import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Stream;

/**
* This extension implements a Parameterized Test that can mock Switcher results and
* reset after its conclusion
*
* @author Roger Floriano (petruki)
*/
class SwitcherMockExtension implements AfterTestExecutionCallback,
ArgumentsProvider, AnnotationConsumer<SwitcherMock> {

private static final String STORE_KEYS = "store_keys";
private static final String STORE_KEY = "store_key";

private String key;

private boolean result;

private SwitcherMockValue[] switchers;

@Override
public void accept(SwitcherMock switcherTester) {
this.key = switcherTester.key();
this.result = switcherTester.result();
this.switchers = switcherTester.switchers();
}

@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
if (ArrayUtils.isNotEmpty(switchers)) {
return provideMultipleArguments(context);
}

return provideSingleArgument(context);
}

@Override
public void afterTestExecution(ExtensionContext context) {
Optional<ExtensionContext> parent = context.getParent();
if (parent.isPresent()) {
Store store = getStore(parent.get());
String[] keys = store.remove(STORE_KEYS, String[].class);

if (ArrayUtils.isNotEmpty(keys)) {
for (String keyStored : keys) {
SwitcherExecutor.forget(keyStored);
}
} else {
String switcherKey = store.remove(STORE_KEY, String.class);
SwitcherExecutor.forget(switcherKey);
}
}
}

private Stream<? extends Arguments> provideMultipleArguments(ExtensionContext context) {
String[] keys = Arrays.stream(switchers)
.map(SwitcherMockValue::key)
.toArray(String[]::new);

for (SwitcherMockValue value : switchers) {
SwitcherExecutor.assume(value.key(), value.result());
}

getStore(context).put(STORE_KEYS, keys);
return Stream.of(Arguments.of(keys, null));
}

private Stream<? extends Arguments> provideSingleArgument(ExtensionContext context) {
SwitcherExecutor.assume(key, result);
getStore(context).put(STORE_KEY, key);

return Stream.of(Arguments.of(key, null));
}

private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass(), context));
}

}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.github.switcherapi.client;

public @interface SwitcherMockValue {

String key();

boolean result() default true;

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,12 @@ public class ClientLocalService {
private static final String STRATEGY_FAIL_NO_INPUT_PATTERN = "Strategy %s did not receive any input";
private static final String CRITERIA_SUCCESS = "Success";

private static ClientLocalService instance;
private final ValidatorService validatorService;

private ClientLocalService() {
public ClientLocalService() {
this.validatorService = new ValidatorService();
}

public static ClientLocalService getInstance() {
if (instance == null) {
instance = new ClientLocalService();
}
return instance;
}

public List<String> checkSwitchers(final Set<String> switchers, final Domain domain) {
List<String> notFound = new ArrayList<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,14 @@ public class SwitcherLocalService extends SwitcherExecutor {
private static final Logger logger = LogManager.getLogger(SwitcherLocalService.class);

private final ClientRemote clientRemote;

private final ClientLocalService clientLocalService;

private Domain domain;

public SwitcherLocalService() {
this.clientRemote = new ClientRemoteService();
this.clientLocalService = new ClientLocalService();
this.init();
}

Expand Down Expand Up @@ -72,7 +75,7 @@ public CriteriaResponse executeCriteria(final Switcher switcher) {
response = this.clientRemote.executeCriteria(switcher);
SwitcherUtils.debug(logger, "[Remote] response: {}", response);
} else {
response = ClientLocalService.getInstance().executeCriteria(switcher, this.domain);
response = this.clientLocalService.executeCriteria(switcher, this.domain);
SwitcherUtils.debug(logger, "[Local] response: {}", response);
}

Expand All @@ -97,7 +100,7 @@ public void checkSwitchers(final Set<String> switchers) {
throw new SwitcherContextException("Snapshot not loaded");
}

final List<String> response = ClientLocalService.getInstance().checkSwitchers(switchers, this.domain);
final List<String> response = this.clientLocalService.checkSwitchers(switchers, this.domain);
if (!response.isEmpty()) {
throw new SwitchersValidationException(response.toString());
}
Expand Down
3 changes: 3 additions & 0 deletions src/test/java/com/github/switcherapi/Switchers.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public class Switchers extends SwitcherContext {
@SwitcherKey
public static final String USECASE111 = "USECASE111";

@SwitcherKey
public static final String USECASE112 = "USECASE112";

@SwitcherKey
public static final String USECASE12 = "USECASE12";

Expand Down
42 changes: 27 additions & 15 deletions src/test/java/com/github/switcherapi/client/SwitcherBypassTest.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package com.github.switcherapi.client;

import static com.github.switcherapi.Switchers.USECASE11;
import static com.github.switcherapi.Switchers.USECASE111;
import static com.github.switcherapi.client.SwitcherContext.getSwitcher;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.nio.file.Paths;

import com.github.switcherapi.client.model.Switcher;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;

import com.github.switcherapi.client.model.Switcher;
import java.nio.file.Paths;

import static com.github.switcherapi.Switchers.*;
import static com.github.switcherapi.client.SwitcherContext.getSwitcher;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class SwitcherBypassTest {

Expand Down Expand Up @@ -93,8 +90,7 @@ void shouldReturnFalse_afterAssumingItsTrue() {
SwitcherExecutor.forget(USECASE111);
assertFalse(switcher.isItOn());
}

@ParameterizedTest

@SwitcherMock(key = USECASE111, result = false)
void shouldReturnFalse_usingParametrizedTest() {
//given
Expand All @@ -105,9 +101,8 @@ void shouldReturnFalse_usingParametrizedTest() {
Switcher switcher = getSwitcher(USECASE111);
assertFalse(switcher.isItOn());
}

@ParameterizedTest
@SwitcherMock(key = USECASE111, result = true)

@SwitcherMock(key = USECASE111)
void shouldReturnTrue_usingParametrizedTest() {
//given
SwitcherContext.configure(ContextBuilder.builder().snapshotLocation(SNAPSHOTS_LOCAL).environment(FIXTURE2));
Expand All @@ -118,4 +113,21 @@ void shouldReturnTrue_usingParametrizedTest() {
assertTrue(switcher.isItOn());
}

@SwitcherMock(switchers = {
@SwitcherMockValue(key = USECASE111),
@SwitcherMockValue(key = USECASE112)
})
void shouldReturnTrue_usingParametrizedTestWithMultipleValues() {
//given
SwitcherContext.configure(ContextBuilder.builder().snapshotLocation(SNAPSHOTS_LOCAL).environment(FIXTURE2));
SwitcherContext.initializeClient();

//test
Switcher switcher = getSwitcher(USECASE111);
assertTrue(switcher.isItOn());

switcher = getSwitcher(USECASE112);
assertTrue(switcher.isItOn());
}

}
6 changes: 6 additions & 0 deletions src/test/resources/snapshot/fixture2.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
"description": "Simple test - Domain disabled",
"activated": true,
"components": ["switcher-client"]
},
{
"key": "USECASE112",
"description": "Simple test - Domain disabled",
"activated": true,
"components": ["switcher-client"]
}
]
}
Expand Down