用Mockito注入DozerBeanMapper

时间:2018-04-20 10:27:05

标签: java mockito dozer

我在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!

3 个答案:

答案 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));
    }
}