You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Java:Mockito测试调用静态方法的函数报错及写法指导

How to Unit Test a Function That Calls Static Methods

Hey there! Let's break down what's going wrong with your test and fix it properly.

Why Your Current Test Fails

  1. Static Methods Don't Belong to Instances: You tried to spy a Helper instance, but priceDifference is a static method—it's tied to the Helper class itself, not any specific instance. So your spy does nothing to affect the static method call in TradesHelper.calculatePL.
  2. Incorrect Stubbing Syntax & Parameter Matching: You used new Market() and new Trade() in your stub, but your test uses mocked market and trade objects. 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.
  3. 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 MockedStatic in 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 market and trade objects in the stub, so the static method call in calculatePL matches exactly.
  • Stub All Dependencies: Since calculatePL uses both priceDifference and effectiveValue from Helper, we need to stub both. We also stub the non-static methods on market and trade because 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:28:15