【问题标题】:Issue when unit testing a service using Thymeleaf template Engine使用 Thymeleaf 模板引擎对服务进行单元测试时出现问题
【发布时间】:2017-09-25 03:47:42
【问题描述】:

我在对我的服务进行单元测试时遇到了 nullPointerException,但我不明白为什么?我正在使用 Spring Boot。 这是我提供模板的简单服务。我自动装配了 TemplateEngine 组件。

@Service
public class TicketTemplatingService implements ITemplatingService{

    @Autowired
    private TemplateEngine templateEngine;

    /**
     * This method will return a ticket template
     */
    @Override
    public String buildHtmlTemplating(Object object, String templateName) {
        Ticket ticket= (Ticket)object;
        //Build the template
        Context context = new Context();
        context.setVariable("id", ticket.getId());
        context.setVariable("date", ticket.getDate());        
        return  templateEngine.process(templateName, context);
    }

}

该类的单元测试如下:

@SpringBootTest
@RunWith(SpringRunner.class)
@ActiveProfiles("test")
public class TemplatingServiceTest {


    @InjectMocks
    private TicketTemplatingService ticketTemplatingService;

    @Mock
    private TemplateEngine templateEngine;

    @Before
    public void setup(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testHtmlTemplateReturnTheHtmlTemplate(){
        Ticket ticket= new Ticket();
        ticket.setId(1L);
        Date date=new Date();
        ticket.setDate(date);

        Context context=new Context();
        context.setVariable("id", 1L);
        context.setVariable("date", date);

        //Mock the process method of the templateEngine bean
        when(templateEngine.process("TemplateName", refEq(context))).thenReturn("Html template result");

        //Now we can test the method
        String htmlTemplate=ticketTemplatingService.buildHtmlTemplating(ticket, "TemplateName");
        assertThat(htmlTemplate).isEqualTo("Html template result");
    }
}

在这个测试类中, templateEngine 变量模拟返回 null,然后我在执行此操作时得到 nullPointerException "when(templateEngine.process("TemplateName", refEq(context))).thenReturn("Html template result"); "

请问您能帮帮我吗?我真的不明白为什么。

【问题讨论】:

    标签: unit-testing spring-boot mockito


    【解决方案1】:

    我在使用 Mokito 测试百里香模板时遇到了与您相同的问题。根据我的研究,您可能想尝试:

    1. 检查您的 Thymeleaf jar 的版本。如果你使用 spring-boot-starter-thymeleaf 依赖,它可能仍然使用

    根据此链接:Final methods in TemplateEngine make it difficult to mock 3.0版本对此类问题有更好的解决方案。

    如果您使用的是 3.0+ 版本,那么 PowerMock 可以来拯救。 参考这个链接:https://github.com/powermock/powermock/wiki/mockfinal 关于如何模拟最终方法(此链接使用 EasyMock)

    如果您使用的是

    祝你研究顺利,希望有更多的人才来回答这个问题。

    【讨论】:

      【解决方案2】:

      代替

      @Autowired
      private TemplateEngine templateEngine;
      

      在你的服务中使用这个接口。

      import org.thymeleaf.ITemplateEngine;
      
      @Autowired
      private ITemplateEngine templateEngine;
      

      并且在您的测试类中使用与 Mock 相同的类

      @Mock
      private ITemplateEngine emailTemplateEngine;
      
      @Before
      public void setup(){
          @when(emailTemplateEngine.process(eq(TEMPLATE_USER_CREATION), any(Context.class))).thenReturn(userCreationHtml);
           .
           .
           .
      }
      

      【讨论】:

      • 赞成。你能提供接口的原因吗?
      • 这在 mockito 中不起作用,您无法测试最终方法,并且 TemplateEngine 的 process() 是最终的
      【解决方案3】:

      @Mengru 怎么说,Mockito 在最终类和方法方面存在问题,但这可以通过一个简单的配置文件解决:https://www.baeldung.com/mockito-final。不知道这个文件有没有什么影响或问题,你可以试一试。

      或者@Mengru 和@cazador 怎么说,在3.0+ 版本中,您可以将其替换为接口ITemplateEngine

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多