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

如何为JPhotoFrame编写JUnit测试?价格计算逻辑测试指导

第一步:重构代码,分离业务逻辑

原代码把UI和费用计算逻辑耦合在itemStateChanged方法里,直接测试UI组件会很麻烦。先把计算逻辑抽成独立类,方便后续单元测试:

package PhotoFrame;

public class PortraitCalculator {
    public static final double LOC_PRICE = 90.00;
    public static final double STUDIO_PRICE = 40.00;
    public static final double ONE_HUMAN_SUBJECT_PRICE = 40.00;
    public static final double MORE_HUMAN_SUBJECTS_PRICE = 75.00;
    public static final double PET_SUBJECT_PRICE = 95.00;

    public static double calculateTotal(boolean isStudioSelected, boolean isLocationSelected,
                                       boolean isOneHumanSelected, boolean isMoreHumansSelected,
                                       boolean isPetSelected) {
        double total = 0.0;

        // 处理拍摄地点(二选一)
        if (isStudioSelected) {
            total += STUDIO_PRICE;
        } else if (isLocationSelected) {
            total += LOC_PRICE;
        }

        // 处理拍摄主体(可多选)
        if (isOneHumanSelected) {
            total += ONE_HUMAN_SUBJECT_PRICE;
        }
        if (isMoreHumansSelected) {
            total += MORE_HUMAN_SUBJECTS_PRICE;
        }
        if (isPetSelected) {
            total += PET_SUBJECT_PRICE;
        }

        return total;
    }
}

然后修改原JPhotoFrame的itemStateChanged方法,调用这个计算器:

@Override
public void itemStateChanged(ItemEvent check) {
    double total = PortraitCalculator.calculateTotal(
            studioBox.isSelected(),
            locBox.isSelected(),
            oneBox.isSelected(),
            moreBox.isSelected(),
            petBox.isSelected()
    );
    totPrice.setText(String.format("%.2f", total));
}
第二步:编写JUnit测试用例

以JUnit 5为例,编写测试类覆盖所有核心场景,常用的Assert语句说明:

  • Assert.assertEquals:验证计算结果是否符合预期(浮点数需指定误差范围)
  • 若需验证布尔逻辑,可使用Assert.assertTrue/Assert.assertFalse,这里核心用assertEquals

测试代码示例:

package PhotoFrame;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;

public class PortraitCalculatorTest {

    // 仅选Studio
    @Test
    void testOnlyStudio() {
        double total = PortraitCalculator.calculateTotal(true, false, false, false, false);
        assertEquals(40.00, total, 0.001); // 第三个参数是允许的误差,避免浮点数精度问题
    }

    // 仅选On Location
    @Test
    void testOnlyLocation() {
        double total = PortraitCalculator.calculateTotal(false, true, false, false, false);
        assertEquals(90.00, total, 0.001);
    }

    // Studio + 1个人类主体
    @Test
    void testStudioAndOneHuman() {
        double total = PortraitCalculator.calculateTotal(true, false, true, false, false);
        assertEquals(80.00, total, 0.001);
    }

    // Location + 多人类主体 + 宠物
    @Test
    void testLocationMoreHumansAndPet() {
        double total = PortraitCalculator.calculateTotal(false, true, false, true, true);
        assertEquals(260.00, total, 0.001);
    }

    // 未勾选任何选项
    @Test
    void testNoOptions() {
        double total = PortraitCalculator.calculateTotal(false, false, false, false, false);
        assertEquals(0.00, total, 0.001);
    }

    // 同时选Studio和Location(UI中ButtonGroup会限制,但测试逻辑分支)
    @Test
    void testStudioAndLocationBothSelected() {
        double total = PortraitCalculator.calculateTotal(true, true, false, false, false);
        assertEquals(40.00, total, 0.001); // 逻辑优先Studio
    }
}
第三步:UI交互测试(可选)

如果需要验证UI组件的交互逻辑,可使用AssertJ Swing库,示例:

package PhotoFrame;

import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class JPhotoFrameUITest {
    private FrameFixture window;

    @BeforeEach
    void setUp() {
        JPhotoFrame frame = GuiActionRunner.execute(JPhotoFrame::new);
        window = new FrameFixture(frame);
        window.show();
    }

    @Test
    void testStudioAndPetSelection() {
        window.checkBox("In studio").check();
        window.checkBox("Pet subject ").check();
        window.textBox().requireText("135.00");
    }

    @AfterEach
    void tearDown() {
        window.cleanUp();
    }
}
关键注意事项
  • 浮点数测试必须指定误差范围,避免因精度问题导致测试失败
  • 优先测试独立业务逻辑,比直接测试UI更稳定、高效
  • 覆盖所有边界场景:空选择、互斥选项、多选组合等

内容的提问来源于stack exchange,提问作者Amiibo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 16:15:38