我在Spring服务中使用Dozer。如何使用JUnit和Mockito将DozerBeanMapper
注入到测试的服务中?
我的java类(如果简化)看起来像:
@Service
public class UnicornService {
private final DozerBeanMapper dozer;
@Autowired
public UnicornService(DozerBeanMapper dozer) {
this.dozer = dozer;
}
public UnicornDto convert(Unicorn unicorn) {
return dozer.map(unicorn, UnicornDto.class);
}
}
使用JUnit 4 + Mockito + Hamcrest的测试类看起来像:
import static com.shazam.shazamcrest.MatcherAssert.assertThat;
import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs;
@RunWith(MockitoJUnitRunner.class)
public class UnicornServiceTest {
@Mock
private DozerBeanMapper dozer;
@InjectMocks
private UnicornService unicornService;
@Test
public void testConvert() throws Exception {
final Unicorn original = ...
final UnicornDto expected = ...
// Execute the method being tested
final UnicornDto result = unicornService.convert(original);
// Validation
assertThat(result, sameBeanAs(expected));
}
}
问题是模拟的Dozer实例没有按预期映射对象 - 默认情况下,Mockito存根返回空或空对象。如果我从测试中删除@Mock
注释,它会抛出NPE!
答案 0 :(得分:2)
在DozerBeanMapper
对象上使用@Spy
注释。这将允许您调用对象的所有常规方法,同时此对象仍由Mockito管理(作为模拟)并注入到测试服务中。
@RunWith(MockitoJUnitRunner.class)
public class UnicornServiceTest {
@Spy
private DozerBeanMapper dozer;
@InjectMocks
private UnicornService unicornService;
// ...
答案 1 :(得分:0)
我发现的另一个解决方案是重构您的代码。它对我来说似乎不那么有吸引力,因为只是为了编写测试,它会带来更大的伤害。
通过服务中的setter使用注入
@Service
public class UnicornService {
private DozerBeanMapper dozer;
@Autowired
public setDozer(DozerBeanMapper dozer) {
this.dozer = dozer;
}
public UnicornDto convert(Unicorn unicorn) {
return dozer.map(unicorn, UnicornDto.class);
}
}
重构测试:
@RunWith(MockitoJUnitRunner.class)
public class UnicornServiceTest {
@InjectMocks
private UnicornService unicornService;
@Before
public void injectDozer() {
final DozerBeanMapper dozer = new DozerBeanMapper();
unicornService.setDozer(dozer);
}
// ...
答案 2 :(得分:0)
您不应该依赖映射器创建一个合适的对象,只需要服务调用映射器并返回其结果。应在映射器的单元测试中测试实际映射。即
@RunWith(MockitoJUnitRunner.class)
public class UnicornServiceTest {
@Mock
private DozerBeanMapper dozer;
@InjectMocks
private UnicornService unicornService;
@Test
public void testConvert() throws Exception {
final Unicorn original = mock(Unicorn.class);
final UnicornDto expected = mock(UnicornDto.class);
when(dozer.map(original, UnicornDto.class)).thenReturn(expected);
// Execute the method being tested
final UnicornDto result = unicornService.convert(original);
// Validate that the call was delegated to the mapper
assertThat(result, is(expected));
}
}