使用Mockito混合Mo豆

时间:2018-08-01 19:35:43

标签: unit-testing spring-boot mockito

我正在使用Mockito / JUnit和Java Spring应用程序编写单元测试。我有一个Service类,该类具有一些注入的依赖项(使用@Autowired字段依赖关系注入,尽管可以更改)。其中一些是项目中的其他依赖项(例如数据访问对象),另一些是库中的各种实用程序类(例如Jackson ObjectMapper)。由于“不测试其他人的代码”的原则,我想模拟前一类的依赖关系,而不是后者。我该怎么做?

更具体地讲,假设我有这个课程:

@Service
public class MyService {
    @Autowired
    private MyRepository dao; //extends CrudRepository, annotated with @Repository

    @Autowired
    private ObjectMapper objectMapper; 
    //Jackson library, injected from Java @Configuration annotated class

    public <...> myFunction(...){
        <...do something with the above 2 objects...>
    }
}

我想为此课程编写一个测试,如下所示:

public class MyServiceUnitTest {
    @Mock
    private MyRepository mockedRepository;

    @InjectMocks
    private MyService testedService; 
    //should inject mockedRepository and a real ObjectMapper from appconfig

    <...>
}

我需要哪种类型的注释,配置文件等?目前,我的测试班级用@RunWith(SpringJUnit4ClassRunner.class)注释,但这似乎不起作用。我还尝试过将@RunWith(SpringRunner.class)@SpringBootTest结合使用,但也没有用。

2 个答案:

答案 0 :(得分:1)

有很多方法可以做到这一点。但这就是我要解决的方法。

  1. 在MyService类中将字段注入更改为构造函数注入

    private MyRepository dao; 
    private ObjectMapper objectMapper; 
    
    @Autowired
    public MyService (MyRepository dao, ObjectMapper objectMapper) {
      this.dao = dao;
      this.objectMapper = objectMapper;
    }
    
  2. 像这样编写测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = {ObjectMapper.class})
    public class MyServiceUnitTest {
    
     @Autowired
     ObjectMapper objectMapper;
    
     @Mock
     private MyRepository dao; //extends CrudRepository, annotated with @Repository
    
     private MyService myService;
    
     @Before
     public void setup() {
        MockitoAnnotations.initMocks(this);
        myService=  new MyService(dao, objectMapper);
     }
    
     @Test
     public void someTest() {
       .........
     }
    }
    

    这样,您可以控制可以模拟服务中的哪些变量,而不必模拟哪些变量。
    使用@ContextConfiguration,可以指定需要加载的框架。这样,当您在测试中对其自动布线时,它不会失败。并且还可以使用它为测试指定仅必需的类,而不是所有内容。

您也可以通过Field Injection和@InjectMocks来实现。但是使用构造函数注入会更好。

答案 1 :(得分:-1)

问题是您的跑步者班。

@RunWith(MockitoJUnitRunner.class)

将为您带来预期的行为。

记住要拨打电话

 MockitoAnnotations.initMocks(this);

作为设置过程的一部分。

相关问题