Android Java:Mockito测试调用静态方法的函数报错及写法指导
Hey there! Let's break down what's going wrong with your test and fix it properly.
Why Your Current Test Fails
- Static Methods Don't Belong to Instances: You tried to spy a
Helperinstance, butpriceDifferenceis a static method—it's tied to theHelperclass itself, not any specific instance. So your spy does nothing to affect the static method call inTradesHelper.calculatePL. - Incorrect Stubbing Syntax & Parameter Matching: You used
new Market()andnew Trade()in your stub, but your test uses mockedmarketandtradeobjects. These won't match, and even if they did, the way you're trying to stub a static method isn't supported by regular Mockito spies/mocks. - Unfinished Stubbing Error: This is a side effect of the above issues—Mockito gets confused because you're trying to stub a static method using instance-based syntax, which isn't valid.
Correct Approach with Mockito 3.4.0+
Starting from Mockito 3.4.0, you can mock static methods directly using MockedStatic. Here's how to rewrite your test properly:
First, make sure your build file (Maven pom.xml or Gradle build.gradle) has a Mockito version ≥3.4.0.
Then, here's the fixed test code:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) // Automatically initializes mocks public class TradesHelperTest { @Mock Market market; @Mock Trade trade; @Test public void calculatePlFromPips_Test() { // Define mock values for our test double mockPriceDiff = 0.0012999999999999678; double mockMarketSize = 10.0; // Adjust to match your test scenario double mockTradeQuantity = 5.0; // Adjust to match your test scenario double mockEffectiveValue = 100.0; // Adjust to match your test scenario // Mock the static methods in the Helper class try (MockedStatic<Helper> mockedHelper = mockStatic(Helper.class)) { // Stub priceDifference to return our mock value when called with our mocked objects mockedHelper.when(() -> Helper.priceDifference(market, trade)) .thenReturn(mockPriceDiff); // Stub effectiveValue too, since calculatePL depends on it mockedHelper.when(() -> Helper.effectiveValue(market)) .thenReturn(mockEffectiveValue); // Stub non-static methods on our mocked market and trade when(market.getSize()).thenReturn(mockMarketSize); when(trade.getQuantity()).thenReturn(mockTradeQuantity); // Execute the method we're testing double result = TradesHelper.calculatePL(market, trade); // Verify the result matches our expected calculation double expectedPl = (mockPriceDiff / mockMarketSize) * mockTradeQuantity * mockEffectiveValue; assertEquals(expectedPl, result); // Optional: Verify the static methods were called with the correct parameters mockedHelper.verify(() -> Helper.priceDifference(market, trade)); mockedHelper.verify(() -> Helper.effectiveValue(market)); } // The try-with-resources block automatically cleans up the static mock } }
Key Notes:
- Try-With-Resources: We use
MockedStaticin a try-with-resources block to ensure the static mock is cleaned up after the test, so it doesn't interfere with other tests in your suite. - Parameter Matching: We use our actual mocked
marketandtradeobjects in the stub, so the static method call incalculatePLmatches exactly. - Stub All Dependencies: Since
calculatePLuses bothpriceDifferenceandeffectiveValuefromHelper, we need to stub both. We also stub the non-static methods onmarketandtradebecause those are part of the calculation logic. - Verification: Optional but useful—we can confirm that the static methods were called with the right arguments to ensure our code is behaving as expected.
Alternative (If You Can Refactor Code)
If you have the option to refactor your production code, consider wrapping static methods in a non-static class (like a HelperService) that you can inject into TradesHelper. This makes testing easier without needing static mocks:
// Refactored non-static helper class public class HelperService { public double priceDifference(Market market, Trade trade) { // Existing logic here } public double effectiveValue(Market market) { // Existing logic here } } // Refactored TradesHelper with constructor injection public class TradesHelper { private final HelperService helperService; public TradesHelper(HelperService helperService) { this.helperService = helperService; } public double calculatePL(Market market, Trade trade) { double pl = (helperService.priceDifference(market, trade) / market.getSize()) * trade.getQuantity() * helperService.effectiveValue(market); return pl; } }
Then your test becomes simpler—just mock HelperService like any other dependency, no static mocks required!
内容的提问来源于stack exchange,提问作者Sindhu

