我在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存根返回空或null对象。如果我从测试中删除@Mock
注释,它将抛出NPE!
发布于 2018-04-20 18:27:05
在DozerBeanMapper
对象上使用@Spy
注释。这将允许您调用对象的所有常规方法,同时此对象仍由Mockito管理(作为模拟)并注入到测试的服务中。
@RunWith(MockitoJUnitRunner.class)
public class UnicornServiceTest {
@Spy
private DozerBeanMapper dozer;
@InjectMocks
private UnicornService unicornService;
// ...
发布于 2018-04-20 18:32:46
我找到的另一个解决方案是重构你的代码。它对我来说似乎不那么有吸引力,因为仅仅为了编写测试,它弊大于利。
在服务中通过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);
}
// ...
发布于 2018-04-20 18:34:12
您根本不应该依赖映射器创建适当的对象,而只是服务调用映射器并返回其结果。应该在映射器的单元测试中测试实际的映射。即
@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));
}
}
https://stackoverflow.com/questions/49939544
复制相似问题