我正在尝试使用 Java 中的 Mockito 和静态模拟创建多个测试用例。它们在单独运行时运行良好,但是当我运行整个测试类时,首先运行的模拟方法(在本例中 shouldRequirePricingIfSucceeding)也会影响其他测试用例(在本例中 shouldNotRequirePricingIfRequestFails 永远不会失败)。我现在尝试将所有我嘲笑的东西放在他们自己的测试方法中,但即使这样也行不通。这是我的代码:
public class PricingService {
public static final int PRODUCT_CODE = 10;
private final ZoneId zoneId = ZoneId.of("UTC");
private static final Logger LOGGER = LoggerFactory.getLogger(PricingService.class);
private static final PricingOauthApi pricingOauthApi = PricingOauthApiFactory.create();
private static final PricingApi pricingApi = PricingApiFactory.create();
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX");
public boolean requiresPricingBeforeSendPush(PushCSCTransaction pushCSCTransaction) {
int transactionType = pushCSCTransaction.getCscTransaction().getTransactionType();
if (!pushCSCTransaction.getControlArea().getSource().equals("TEST") ||
transactionType != 30 &&
transactionType != 31)
return false;
boolean sendRequestSuccessfully = sendPriceRequest(pushCSCTransaction);
return sendRequestSuccessfully && transactionType == 31;
}
private boolean sendPriceRequest(PushCSCTransaction pushCSCTransaction) {
try {
OauthRequest oauthRequest = new OauthRequest(Configuration.Pricing.getOauthScope(), Configuration.Pricing.getOauthClientId(), Configuration.Pricing.getOauthClientSecret());
Response<OauthResponse> oauthResponse = pricingOauthApi.oauth(oauthRequest, Configuration.Pricing.getOauthPathId()).execute();
if (!oauthResponse.isSuccessful() || oauthResponse.body() == null) throw new WebApplicationException("");
Response<Void> response = pricingApi.pricing(pushCSCTransaction, "Bearer " + oauthResponse.body().getAccessToken()).execute();
return response.isSuccessful();
} catch (Exception exception) {
LOGGER.error("Error when trying to send transaction message", exception);
return false;
}
}
}
@ExtendWith(MockitoExtension.class)
public class PricingServiceTest {
@Test
public void shouldNotRequirePricingIfRequestFails() throws IOException {
PricingApi pricingApi = mock();
PricingOauthApi pricingOauthApi = mock();
try (MockedStatic<PricingApiFactory> pricingApiFactory = Mockito.mockStatic(PricingApiFactory.class);
MockedStatic<PricingOauthApiFactory> pricingOauthApiFactory = Mockito.mockStatic(PricingOauthApiFactory.class)) {
pricingApiFactory.when(PricingApiFactory::create).thenReturn(pricingApi);
pricingOauthApiFactory.when(PricingOauthApiFactory::create).thenReturn(pricingOauthApi);
Call<OauthResponse> call = mock(Call.class);
Mockito.when(pricingOauthApi.oauth(Mockito.any(), Mockito.any())).thenReturn(call);
Mockito.when(call.execute()).thenThrow(new IOException("Test"));
PushCSCTransaction transaction = createCsvTransaction("TEST", 31, PRODUCT_CODE, 1312, 311, 1);
PricingService service = new PricingService();
boolean result = service.requiresPricingBeforeSendPush(transaction);
assertFalse(result);
Mockito.verify(pricingOauthApi).oauth(Mockito.any(), Mockito.any());
Mockito.verify(pricingApi, Mockito.never()).pricing(Mockito.any(), Mockito.any());
}
}
@Test
public void shouldRequirePricingIfSucceeding() throws IOException {
PricingApi pricingApi = mock();
PricingOauthApi pricingOauthApi = mock();
try (MockedStatic<PricingApiFactory> pricingApiFactory = Mockito.mockStatic(PricingApiFactory.class);
MockedStatic<PricingOauthApiFactory> pricingOauthApiFactory = Mockito.mockStatic(PricingOauthApiFactory.class)) {
pricingApiFactory.when(PricingApiFactory::create).thenReturn(pricingApi);
Call<Void> call = mock(Call.class);
Mockito.when(pricingApi.pricing(Mockito.any(), Mockito.any())).thenReturn(call);
Mockito.when(call.execute()).thenReturn(Response.success(null));
pricingOauthApiFactory.when(PricingOauthApiFactory::create).thenReturn(pricingOauthApi);
Call<OauthResponse> callOauth = mock(Call.class);
Mockito.when(pricingOauthApi.oauth(Mockito.any(), Mockito.any())).thenReturn(callOauth);
OauthResponse oauthResponse = new OauthResponse();
Mockito.when(callOauth.execute()).thenReturn(Response.success(oauthResponse));
PushCSCTransaction transaction = createCsvTransaction("TEST", 31, PRODUCT_CODE, 1312, 311, 1);
PricingService service = new PricingService();
boolean result = service.requiresPricingBeforeSendPush(transaction);
assertTrue(result);
Mockito.verify(pricingOauthApi).oauth(Mockito.any(), Mockito.any());
Mockito.verify(pricingApi).pricing(Mockito.any(), Mockito.any());
}
}
}
因此,当我运行此代码时,我现在总是从 sendPriceRequest 得到 true,因为模拟永远不会更改以引发异常。我忘记取消模拟静态方法是什么?我正在使用 Java 8 和mockito版本4.11.0和junit 5。
还尝试添加:
@BeforeEach
public void setUp() {
Mockito.clearAllCaches();
}
但这也不起作用。
该问题与模拟静态方法无关。 您的
mockStatic
调用已正确包装在 try-with-resources 块中。
问题出在您的
PricingService
中,它使用静态字段。
静态字段 pricingOauthApi
和 pricingApi
仅初始化一次 - 当您创建服务的第一个实例时。
观察更简单的例子:
class FooCollaborator {
}
class FooService {
static FooCollaborator fooCollaborator = createFoo();
static FooCollaborator createFoo() {
System.out.println("static createFoo called");
return new FooCollaborator();
}
}
public class StaticTest {
@Test
void test1() {
System.out.println("test1");
FooService fooService = new FooService();
System.out.println(fooService.fooCollaborator);
}
@Test
void test2() {
System.out.println("test2");
FooService fooService = new FooService();
System.out.println(fooService.fooCollaborator);
}
}
输出:
test1
static createFoo called
com.so.examples.mockito.FooCollaborator@327514f
test2
com.so.examples.mockito.FooCollaborator@327514f