Mockito注入嵌套bean

时间:2016-05-25 15:00:40

标签: java spring junit dependency-injection mockito

我对mockito不是新手,但这次我在工作中发现了一个有趣的案例。我希望你能帮助我。

我需要注入mock来改变测试期间的某些方法行为。问题是,bean结构是嵌套的,并且这个bean在其他bean中,不能从test方法访问。我的代码如下所示:

@Component
class TestedService { 
  @Autowired
  NestedService nestedService;
}

@Component
class NestedService {
  @Autowired
  MoreNestedService moreNestedService;
}

@Component
class MoreNestedService {
  @Autowired
  NestedDao nestedDao;
}

@Component
class NestedDao {
  public int method(){
    //typical dao method, details omitted
  };
}

所以在我的测试中,我希望调用NestedDao.method来返回模拟的答案。

class Test { 
  @Mock
  NestedDao nestedDao;

  @InjectMocks
  TestedService testedSevice;

  @Test
  void test() {
    Mockito.when(nestedDao.method()).thenReturn(1);
    //data preparation omitted
    testedSevice.callNestedServiceThatCallsNestedDaoMethod();
    //assertions omitted
  }
}

我试过做一个initMocks:

@BeforeMethod
  public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

还要在我的测试类上添加注释:

@RunWith(MockitoJUnitRunner.class)

始终从方法获取无效指针或错误答案(未经模拟)。

我猜这个嵌套的调用是错误的,因此无法模仿这个Dao。 我也读过@InjectMocks只适用于setter或构造函数注入,我很遗憾(在私有字段上只是@Autowire),但是当我尝试时它并没有起作用。

有什么猜测我错过了什么? ;)

2 个答案:

答案 0 :(得分:2)

您可以使用@MockBean而不是@Mock和@InjectionMock。

@RunWith(SpringRunner.class)
@SpringBootTest
class Test { 
  @MockBean
  NestedDao nestedDao;

  @Autowired
  TestedService testedSevice;

  @Test
  void test() {
    Mockito.when(nestedDao.method()).thenReturn(1);
    //data preparation omitted
    testedSevice.callNestedServiceThatCallsNestedDaoMethod();
    //assertions omitted
  }
}

答案 1 :(得分:1)

对我来说很有道理,你错了, 为什么? 这是因为您正在测试TestedService以及与NestedService的交互,而不是与Dao的交互,Dao交互应该在NestedService测试中进行验证

看看这个:

@Component
class TestedService { 

  @Autowired
  NestedService nestedService;

  String sayHello(String name){
     String result = "hello" + nestedService.toUpperCase(name)
  }
}

@Component
class NestedService {

  @Autowired
  MoreNestedService moreNestedService;

  String toUpperCase(String name){
        String nameWithDotAtTheEnd = moreNestedService.atDot(name);
        return nameWithDotAtTheEnd.toUpperCase();

  }

}

在你的考试中:

class Test { 
  @Mock
  NestedService nestedService;

  @InjectMocks
  TestedService testedSevice;

  @Test
  void test() {
    Mockito.when(nestedService.toUpperCase("rene")).thenReturn("RENE.");
    //data preparation omitted
    Assert.assertEquals("hello RENE.", testedSevice.sayHello("rene"));
    //assertions omitted
  }
}

如您所见,您假设TestedService的依赖项运行良好,您只需要验证hello是否被添加为字符串的前缀,