Java 用Mockito注射DozerBeanMapper
我在春季服务中使用推土机。如何使用JUnit和Mockito将DozerBeanMapper注入到经过测试的服务中 如果简化,我的java类如下所示:Java 用Mockito注射DozerBeanMapper,java,mockito,dozer,Java,Mockito,Dozer,我在春季服务中使用推土机。如何使用JUnit和Mockito将DozerBeanMapper注入到经过测试的服务中 如果简化,我的java类如下所示: @Service public class UnicornService { private final DozerBeanMapper dozer; @Autowired public UnicornService(DozerBeanMapper dozer) { this.dozer = dozer;
@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);
}
}
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));
}
}
使用JUnit 4+Mockito+Hamcrest的测试类如下所示:
@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);
}
}
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 在DozerBeanMapper对象上使用注释。这将允许您调用该对象的所有常规方法,同时该对象仍由Mockito作为一个mock进行管理,并注入到一个已测试的服务中
@RunWith(MockitoJUnitRunner.class)
public class UnicornServiceTest {
@Spy
private DozerBeanMapper dozer;
@InjectMocks
private UnicornService unicornService;
// ...
我发现的另一个解决方案是重构代码。对我来说,它似乎没有那么吸引人,因为它弊大于利,只是为了编写测试 在服务中通过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);
}
// ...
您根本不应该依赖映射器来创建适当的对象,只需要服务调用映射器并返回其结果即可。实际映射应该在映射器的单元测试中进行测试。即
@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));
}
}
请注意下面的评论:使用真正的间谍应该谨慎,有时,在大多数情况下,这不是您想要设计应用程序的方式。@daniu我考虑到了这一点。正如你所看到的,我提出了两个解决方案。你认为替代方案更好吗?