传递给 when() 的参数不是模拟的! Spring 没有@SpringBootApplication/main class 的引导项目抛出异常

Argument passed to when() is not a mock! exception thrown with Spring Boot project which doesn't have @SpringBootApplication/main class

我的项目是一个简单的 spring 启动应用程序,它没有 main/@SpringBootApplication class。它用作其他模块的依赖库。我正在尝试为这个项目中存在的 classes 编写单元测试,如下所示,并得到下面粘贴的错误。非常感谢任何快速帮助。

pom 依赖项:

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        
        <!-- exclude junit 4 -->
        <exclusions>
            <exclusion>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
     <!-- junit 5 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <scope>test</scope>
    </dependency>

由于此项目没有主 class,使用以下配置获取 spring 应用程序上下文 class。

@Configuration
public class TestServiceConfig {
@Bean
public TestService productService() {
    return Mockito.mock(TestService.class);
}

@Bean
public MongoDriverService productMongo() {
    return Mockito.mock(MongoDriverService.class);
}
}

下面是我的测试 class,它抛出异常。实际 java class 有一个名为 getPlanCode 的方法(需要 6 个参数)和 returns void。在此方法中,mongo 对象用于连接数据库,因此我在服务对象上使用了@InjectMocks。

public class ValidationServiceTest {
@Mock
MongoDriverService mongo;

@InjectMocks
TestService service;

@Test
@DisplayName("Test Get Plan Code positive")
public void getPlanCodeTest() {
    doNothing().when(service).getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());
    
    service.getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());

    verify(service, times(1)).getPlanCode(anyString(), anyString(), any(Batch.class), any(BatchFile.class), any(Document.class), anyString());
    
}
}

以下是例外

12:51:33.829 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - After test method: context [DefaultTestContext@45b4c3a9 testClass = DefaultMedicareBFTAccumsValidationServiceTest, testInstance = com.anthem.rxsmart.service.standalone.batchvalidation.DefaultMedicareBFTAccumsValidationServiceTest@14dda234, testMethod = getPlanCodeTest@DValidationServiceTest, testException = org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to when() is not a mock!
Example of correct stubbing:

service 不是模拟,因为您使用的是 @InjectMocks(假设您使用的是 @RunWith(MockitoRunner.class)@ExtendWith,但您出于某种原因隐藏了它)。

@InjectMocks 所做的,是创建一个新的 TestService 实例,并将模拟注入其中(模拟所需的依赖项)。所以服务是真的,不是假的

IMO 此测试没有意义,因为您应该测试单一实体合同的实施,而不是测试模拟...

你的测试用例和断言毫无意义,因为它就像“调用方法 A 并检查我是否刚刚调用了方法 A”,而你应该检查和验证例如 return 调用的值,或者某些方法是否的模拟已被调用,例如,如果 Mongo 是用适当的参数查询的。我只是希望这是一个非常糟糕的例子,而不是真实的测试场景

测试设置也是错误的,因为你告诉我们你想使用 @Configuration class 和 @Bean 但是你在测试中使用 @Mock为您创建全新的模拟。换句话说 - 根本没有使用该配置

贴出此答案,仅供相同理解状态的开发者使用。

@Test
@DisplayName("Test Get Plan Code positive")
public void getPlanCodeTest() {
    service = new ValidationService(mongo);
    
    Mockito.when(mongo.aggregateIterable("test", pipeline)).thenReturn(tierFilterDocs);
    
    service.getPlanCode("", "", null, batchFile, null, "");
    verify(mongo, times(1)).aggregateIterable("test", pipeline);        
}

我已经更新了我的测试用例,现在它解决了这个问题。现在不需要配置文件,因为我正在测试 class 本身中模拟对象。