This commit is contained in:
2026-08-07 17:46:23 +08:00
parent 98ac9840c2
commit 645c483649
22 changed files with 370 additions and 29 deletions
@@ -4,6 +4,7 @@ import com.baiyue.integration.dto.ocr.OcrCandidate;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -15,21 +16,31 @@ class WeightCandidateSelectorTest {
@Test
void selectsLargestNumericCandidateAndNormalizesDecimalSeparator() {
List<OcrCandidate> candidates = List.of(
new OcrCandidate("10:38", 0.99, 10, 10, 40, 10),
new OcrCandidate(" 12,35 ", 0.97, 20, 30, 120, 60),
new OcrCandidate("29", 0.99, 160, 10, 20, 10),
new OcrCandidate("kg", 0.99, 150, 70, 30, 15));
new OcrCandidate("10:38", new BigDecimal("0.99"), 10, 10, 40, 10),
new OcrCandidate(" 12,35 ", new BigDecimal("0.97"), 20, 30, 120, 60),
new OcrCandidate("29", new BigDecimal("0.99"), 160, 10, 20, 10),
new OcrCandidate("kg", new BigDecimal("0.99"), 150, 70, 30, 15));
WeightCandidateSelector.SelectedWeight selected = selector.select(candidates).orElseThrow();
assertThat(selected.weight()).isEqualByComparingTo("12.35");
assertThat(selected.confidence()).isEqualTo(0.97);
assertThat(selected.confidence()).isEqualByComparingTo("0.97000");
}
@Test
void rejectsNonNumericCandidates() {
assertThat(selector.select(List.of(
new OcrCandidate("kg", 0.99, 0, 0, 20, 10),
new OcrCandidate("10:38", 0.99, 0, 0, 20, 10)))).isEmpty();
new OcrCandidate("kg", new BigDecimal("0.99"), 0, 0, 20, 10),
new OcrCandidate("10:38", new BigDecimal("0.99"), 0, 0, 20, 10)))).isEmpty();
}
@Test
void canonicalizesConfidenceToRangeAndFiveDecimalPlaces() {
assertThat(new OcrCandidate("1", new BigDecimal("0.5097191334"), 0, 0, 1, 1)
.confidence()).isEqualByComparingTo("0.50972");
assertThat(new OcrCandidate("1", new BigDecimal("1.2"), 0, 0, 1, 1)
.confidence()).isEqualByComparingTo("1.00000");
assertThat(new OcrCandidate("1", new BigDecimal("-0.1"), 0, 0, 1, 1)
.confidence()).isEqualByComparingTo("0.00000");
}
}
@@ -19,6 +19,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -56,13 +57,17 @@ class WeightOcrBatchServiceTest {
when(properties.baiduOcr()).thenReturn(properties(inputRoot, outputRoot).baiduOcr());
when(client.recognize(any())).thenReturn(new BaiduMeterClient.MeterResponse(
"{\"words_result\":[]}",
List.of(new OcrCandidate("12.35", 0.98, 10, 10, 80, 30))));
List.of(
new OcrCandidate("12.35", new BigDecimal("0.5097191334"), 10, 10, 80, 30),
new OcrCandidate("KG\u0000", new BigDecimal("0.98"), 10, 50, 30, 10))));
var result = service.recognize(new WeightOcrBatchRequest("batch-a", null, null, null, false));
assertThat(result.total()).isEqualTo(1);
assertThat(result.recognized()).isEqualTo(1);
assertThat(result.results().get(0).status()).isEqualTo(Status.RECOGNIZED);
assertThat(result.results().get(0).confidence()).isEqualByComparingTo("0.50972");
assertThat(result.results().get(0).ocrRawText()).isEqualTo("12.35\nKG ");
Path batchOutput = outputRoot.resolve(result.outputDirectory());
assertThat(batchOutput.resolve("cropped/weight.jpg")).isRegularFile();
assertThat(batchOutput.resolve("raw/weight.json")).isRegularFile();
@@ -0,0 +1,58 @@
package com.baiyue.integration.service.ocr;
import com.baiyue.integration.config.IntegrationProperties;
import com.baiyue.integration.dto.ocr.OcrCandidate;
import com.baiyue.integration.dto.ocr.WeightOcrBatchResult;
import com.baiyue.integration.dto.ocr.WeightOcrImageResult;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.util.unit.DataSize;
import java.math.BigDecimal;
import java.net.URI;
import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@SpringJUnitConfig(WeightOcrSingleImageService.class)
class WeightOcrSingleImageServiceTest {
@TempDir Path tempDirectory;
@MockBean IntegrationProperties properties;
@MockBean WeightOcrBatchService batches;
@Resource WeightOcrSingleImageService service;
@Test
void returnsSafeContractWithoutTemporaryPathsOrCandidateDetails() throws Exception {
var config = new IntegrationProperties.BaiduOcr(true, "key", "secret",
URI.create("https://example.com/token"), URI.create("https://example.com/meter"),
Duration.ofSeconds(1), Duration.ofSeconds(1), tempDirectory, tempDirectory.resolve("out"),
DataSize.ofMegabytes(3), 40_000_000L, 50, Duration.ZERO, 0);
when(properties.baiduOcr()).thenReturn(config);
var imageResult = new WeightOcrImageResult("weight.jpg", "cropped/weight.jpg", "raw/weight.json",
WeightOcrImageResult.Status.RECOGNIZED, new BigDecimal("285.5"),
new BigDecimal("0.5097191334"),
List.of(new OcrCandidate("285.5", new BigDecimal("0.5097191334"), 0, 0, 10, 10)),
"285.5", null);
when(batches.recognize(any())).thenReturn(new WeightOcrBatchResult("batch", Instant.now(),
Instant.now(), "input", "output", 1, 1, 0, 0, List.of(imageResult)));
var result = service.recognize(new MockMultipartFile(
"file", "weight.jpg", "image/jpeg", new byte[]{1, 2, 3}));
assertThat(result.confidence()).isEqualByComparingTo("0.50972");
assertThat(result.ocrRawText()).isEqualTo("285.5");
assertThat(result.sourceImage()).isNull();
assertThat(result.croppedImage()).isNull();
assertThat(result.rawResponseFile()).isNull();
assertThat(result.candidates()).isEmpty();
}
}