使用Spring Boot和JUnit从Controller类模拟存储库

问题描述 投票:0回答:4

我正在为我的控制器类编写测试用例,这是一个Spring Boot应用程序,我想只为控制器类编写测试用例,它调用服务和服务到存储库。我正在使用SpringBootTest,它用于为我的所有bean创建实例。我想只模拟数据库调用和外部api调用。

MyController {

    @Autowired
    MyService service;

    //Api call for getDetails
    service.getDetails();
}


MyService {

   @Autowired
   MyRepository repo;

}

MyControllertest {
    @Autowired
    MyController controller;

    @Mock
    MyRepository repoMock;

    @Before
    public void setup(){
        // intit mocks
    }

    @Test
    public void myTest(){
        when(repoMock.getDetails()).thenReturn(null);
        controller.getdetails();
    }
}

当我运行测试用例时,它不使用模拟存储库,而是使用Service类中提到的@Autowired存储库。

任何人都可以解释我如何从控制器类模拟存储库。

在这个博客中发布了这么多问题,但没有得到任何回复。

junit mocking mockito powermock spring-boot-test
4个回答
2
投票

它没有使用你的Mocks,因为你没有将这些模拟注入你的控制器/服务类。相反,你是自动装配它。 正确的做法是

@RunWith(MockitoJUnitRunner.class)
public class MyControllerTest {

    @InjectMocks
    MyController controller;
    .....

}

更好的解决方案是摆脱Field Injection并使用Constructor Injection

例如,在Controller和Service类中。您可以在Contructor上执行此操作,而不是在Fields上使用@Autowired。例如

class MyService {

   private final MyRepository repo;

   @Autowired
   public MyService(final MyRepository repo) {
      this.repo = repo;
   }
}

同样在Controller类中

class MyController {

    @Autowired
    private final MyService service;

    public MyController(final MyService service) {
         this.service = service
    }
}

这样做可以帮助您在运行时轻松设置模拟。例如,在您的测试类中,您可以这样做

@RunWith(MockitoJUnitRunner.class)
public class MyControllertest {

    MyController controller;
    MyService service;

    @Mock
    MyRepository repoMock;


    @Before
    public void setup(){
        // init mocks
      service = new MyService(repoMock);
      controller = new MyController(service);
    }
  ..............
}

Here是关于Field注入的好文章


0
投票

你不能打电话

MockitoAnnotations.initMocks(this);

setUp方法,因为SpringRunner已经初始化了嘲笑。通过调用initMocks,您可以为repoMock分配一个新对象。像when这样的所有Mockito动作都是在新对象上执行的,但是Spring仍然使用由MyRepository创建的“旧”SpringRunner


0
投票

解决这个问题的3种方法:

1.与Mockito一起。

 @Mock
 MyRepository repoMock;
 @InjectMocks
 MyService service;

这样做的是它按类类型匹配MyService类字段,并将Mocked变量分配给这些字段。所以它会为你的服务注入嘲笑。这与Spring无关。

2.重构MyService构造函数,因此依赖项可以通过构造函数注入。 @Autowired也与构造函数一起工作,因此它是首选方式。

@Autowired
public MyService(MyRespoitory repository){
  this.repository = repository;
}

3.使用Springs测试环境:

https://docs.spring.io/spring-security/site/docs/current/reference/html/test-mockmvc.html

并定义一个bean,它是存储库的模拟版本

@Bean
public MyRepository mockMyRepository(){
  return mock(MyRespository.class);
}

这对于服务测试来说可能是缓慢且令人厌烦的。

第二个是最优选和最简单的方法。


0
投票

这对我有用:

  @MockBean
  private OrderRepository orderRepository;

  @SpyBean
  private OrderService orderService;

  @InjectMocks
  private OrderController orderController;
© www.soinside.com 2019 - 2024. All rights reserved.