Spring 框架 - Mock 不是模拟

Spring Framework - Mock is not mocking

我有一个 Spring MvC 应用程序。 (Spring 框架是 Java 平台的应用程序框架和控制反转容器)与此测试:

    @RunWith(SpringJUnit4ClassRunner.class)
    public class AutorisationServiceTest {
    
        @Autowired
        @InjectMocks
        private IAutorisationService service;
    
        @Mock
        PersonneRepository personneRepository = Mockito.mock(PersonneRepository.class);
    
    
        @Before
        public void setup() {
        }
    
    
        @Test
        public void should_Find_GardeWith2Affectations() throws IOException {
    
            when(personneRepository.getAll(anyString())).thenReturn(DataLoader.mockData());
            service.getAll("rules");
        }
    
    }

    @Service
    public class AutorisationService implements IAutorisationService {
    
        private final PersonneRepository personneRepository;
    
        public AutorisationService(PersonneRepository personneRepository) {
            this.personneRepository = personneRepository;
        }

@Override
    public List<User> getAll(String where) {
        return personneRepository.getAll(where));
    }
    ...
    }

但是当我 运行 测试时似乎不能模拟 repo

您不能同时使用 @MockMockito.mock。选择其中一项

在@Before 设置方法中你需要添加MockitoAnnotations.initMocks(this)。这将注入您的模拟服务。我修改了下面的代码:

@RunWith(SpringJUnit4ClassRunner.class)
    public class AutorisationServiceTest {
    
        @Mock
        PersonneRepository personneRepository;

        @InjectMocks
        private AutorisationService service;
    
        @Before
        public void setup() {
          MockitoAnnotations.initMocks(this);
        }
    
    
        @Test
        public void should_Find_GardeWith2Affectations() throws IOException {
    
            when(personneRepository.getAll(anyString())).thenReturn(DataLoader.mockData());
            service.getAll("rules");
        }
    
    }

    @Service
    public class AutorisationService implements IAutorisationService {
    
        private final PersonneRepository personneRepository;
    
        public AutorisationService(PersonneRepository personneRepository) {
            this.personneRepository = personneRepository;
        }

@Override
    public List<User> getAll(String where) {
        return personneRepository.getAll(where));
    }
    ...
    }

此答案适用于 testng:

MockitoTestExecutionListener初始化mocks,需要使用@MockBean注解

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners(MockitoTestExecutionListener.class)
public class AutorisationServiceTest {   
    @MockBean
    PersonneRepository personneRepository;

此外,不要忘记添加 ResetMocksTestExecutionListener 以防止 inter-test 持久性模拟(参见此 issue)。

您应该决定是要编写 Spring 测试还是 Mockito 测试。

A spring 测试将加载完整的上下文,然后您可以使用 @Autowired@MockBean:

@RunWith(SpringJUnit4ClassRunner.class)
public class AutorisationServiceTest {
    
  @Autowired
  private IAutorisationService service;
    
  @MockBean
  PersonneRepository personneRepository;

Mockito 测试运行得更快,但您将只有使用 @InjectMocks@Mock 显式配置的对象:

@RunWith(MockitoJUnitRunner.class)
public class AutorisationServiceTest {
  
  @InjectMocks
  private IAutorisationService service;
    
  @Mock
  PersonneRepository personneRepository;

请注意,在使用注释和专用运行程序时,您永远不必使用 Mockito.mock() 实例化模拟。

我猜你的 PersonneRepository 是 @Service、@Component 或 @Repository。所以你也应该在这里使用 auto-wiring:

@Service
public class AutorisationService implements IAutorisationService {

   @Autowired    
   private PersonneRepository personneRepository;