在Service层中,注入了TemplateEngine,但是在编写该类的单元测试时,会在TemplateEngine附近报nullPointerException异常。
Service层代码如下:
@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);
}
}
单元测试代码如下:
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);
// 会在这里报空指针异常
when(templateEngine.process("TemplateName", refEq(context))).thenReturn("Html template result");
String htmlTemplate=ticketTemplatingService.buildHtmlTemplating(ticket, "TemplateName");
assertThat(htmlTemplate).isEqualTo("Html template result");
}
}
在TemplateEngine实现类中,所有的process方法带有Fina关键字。导致无法Mock。
public final String process(String template, IContext context) {
return this.process(new TemplateSpec(template, (Set)null, (TemplateMode)null, (String)null, (Map)null), context);
}
public final String process(String template, Set<String> templateSelectors, IContext context) {
return this.process(new TemplateSpec(template, templateSelectors, (TemplateMode)null, (String)null, (Map)null), context);
}
public final String process(TemplateSpec templateSpec, IContext context) {
Writer stringWriter = new FastStringWriter(100);
this.process((TemplateSpec)templateSpec, (IContext)context, (Writer)stringWriter);
return stringWriter.toString();
}
public final void process(String template, IContext context, Writer writer) {
this.process(new TemplateSpec(template, (Set)null, (TemplateMode)null, (String)null, (Map)null), context, writer);
}
public final void process(String template, Set<String> templateSelectors, IContext context, Writer writer) {
this.process(new TemplateSpec(template, templateSelectors, (TemplateMode)null, (String)null, (Map)null), context, writer);
}
解决方法:
将Service层里面的
@Autowired
private TemplateEngine templateEngine;
修改为
import org.thymeleaf.ITemplateEngine;
@Autowired
private ITemplateEngine templateEngine;
并且,在单元测试中,直接注入
@Mock
private ITemplateEngine emailTemplateEngine;
这样就可以直接完成对process的调用。