我如何用Java模拟这个客户端



我试图在Java中正确地模拟这个标志客户端,但我不知道如何做到。通常,我会通过WireMock模拟第三方api(模拟调用(,它会帮助我模拟它并为它添加测试。然而,实际的调用和逻辑在这个客户端对象下被屏蔽,我不确定我是否正确地模拟了它。

以下是文档中的一些代码:https://docs.flagsmith.com/clients/server-side#initialise-sdk

然而,我现在在我的代码库中有这样的设置:

实施:

@Gateway
public class FlagsmithGateway implements FlagsmithPort {
private final FlagsmithClient flagsmithClient;
@Autowired
public FlagsmithGateway(@Value("${flagsmith.environment.id}") String flagsmithEnvironmentId,
@Value("${flagsmith.endpoint}") String flagsmithEndpoint) {
this(FlagsmithClient
.newBuilder()
.setApiKey(flagsmithEnvironmentId)
.withApiUrl(flagsmithEndpoint)
.build());
}
public FlagsmithGateway(FlagsmithClient flagsmithClient) {
this.flagsmithClient = flagsmithClient;
}
@Override
public boolean isEnabled(FeatureFlags flag) throws FlagsmithClientError {
Flags flags = flagsmithClient.getEnvironmentFlags();
return flags.isFeatureEnabled(flag.toString());
}
@Override
public boolean isDisabled(FeatureFlags flag) throws FlagsmithClientError {
Flags flags = flagsmithClient.getEnvironmentFlags();
return !flags.isFeatureEnabled(flag.toString());
}

}

上面实现的测试类:

@ExtendWith(MockitoExtension.class)
public class FlagsmithGatewayTest  {

private FlagsmithGateway flagsmithGateway;
@Mock
private FlagsmithClient flagsmithClient;
@BeforeEach
public void setup() {
flagsmithGateway = new FlagsmithGateway(flagsmithClient);
}
@Test
public void isEnabled_shouldReturnWhetherFeatureIsEnabled() throws FlagsmithClientError {
flagsmithClient = mock(FlagsmithClient.class);
Flags flags = setupFlags("test_toggle", true);
when(flagsmithClient.getEnvironmentFlags()).thenReturn(flags);=
boolean result = flagsmithGateway.isEnabled(FeatureFlags.TOGGLE_FOR_TESTS); 
assertThat(result).isTrue();
}
private static Flags setupFlags(String featureName, Boolean enabled) {
Flags flag = new Flags();
BaseFlag baseFlag = new BaseFlag();
Map<String, BaseFlag> someFlags = new HashMap<>();
baseFlag.setFeatureName(featureName);
baseFlag.setEnabled(enabled);
someFlags.put(featureName,baseFlag);
flag.setFlags(someFlags);
return flag;
}
}

编辑:上面的代码几乎可以工作,但在测试中调用flagsmithGateway.isEnabled(FeatureFlags.TOGGLE_FOR_TESTS)后,我在这一行得到了一个NPE。标志为空

flags.isFeatureEnabled(flag.toString());

为什么?我用的是Junit 5。

要测试FlagsmithGateway,您只需要验证它的方法是否与其依赖项(即FlagsmithClient(正确交互,例如它是否真的用期望的参数调用了期望的方法。在这种情况下,您只需要模拟FlagsmithClient并截断其getEnvironmentFlags()

为了使FlagsmithGateway能够使用模拟的FlagsmithClient,您需要有某种方法将FlagsmithClient传递到它中。(例如,通过构造函数或setter(。因此,首先,我会对您的网关进行一点重构,使其能够直接通过构造函数使用FlagsmithClient进行创建。

@Gateway
public class FlagsmithGateway implements FlagsmithPort {
private final FlagsmithClient flagsmithClient; 
@Autowired
public FlagsmithGateway(@Value("${flagsmith.apikey}") String flagsmithApiKey,
@Value("${flagsmith.endpoint}") String flagsmithEndpoint) {
this(FlagsmithClient
.newBuilder()
.setApiKey(flagsmithApiKey)
.withApiUrl(flagsmithEndpoint)
.build());
}
public FlagsmithGateway(FlagsmithClient flagsmithClient) {
this.flagsmithClient = flagsmithClient;
}
}

测试将使用此构造函数创建FlagsmithGateway:

@ExtendWith(MockitoExtension.class)
public class FlagsmithGatewayTest extends GatewayIntegrationTest {
FlagsmithGateway flagsmithGateway;
@Mock
FlagsmithClient flagsmithClient;
@BeforeEach
public void setup() {
flagsmithGateway = new FlagsmithGateway(flagsmithClient);
}
@Test
public void isEnabled_shouldReturnWhetherFeatureIsEnabled() throws FlagsmithClientError {
Flags flags = defaultFlagHandler("test_toggle", true);
when(client.getEnvironmentFlags()).thenReturn(flags);

FeatureFlags featureFlags = xxxxx //create it based on your logic
boolean result = flagsmithGateway.isEnabled(featureFlags);
assertThat(result).isTrue();
}
}

请注意,我使用普通的Mockito测试来手动创建FlagsmithGateway,但没有使用spring-boot测试,主要是因为您在spring中设置的方式将使其使用构造函数

new FlagsmithGateway(String flagsmithApiKey,String flagsmithEndpoint) 

以创建CCD_ 12,但它总是硬编码为使用真实的CCD_。

如果你真的想验证原始构造函数中的代码是否按预期工作,你可以为它创建另一个测试:

@Test
public void flagsmithClientCreatedProperly(){
FlagsmithGateway gateway = new FlagsmithGateway("apiKey" , "http://foo");
//get the FlagsmithClient from  FlagsmithGateway and the assert tis apiKey and apiUrl 
}

最新更新