首页 > 解决方案 > 当我想忽略其余参数时,如何验证是否使用正确的参数调用服务?

问题描述

我有SomeService一个有方法的类verify(Company company, Location location)Location是枚举 -Location.EUROPELocation.USA. 根据我选择不同的电子邮件模板的位置,我在里面有私有方法SomeService

 private String chooseServiceResource(Location location){
    if(location.equals(Location.EUROPE))
      return "resourceEU";
    return "resourceUSA";
  }

someService(Company company, Location location)我调用chooseServiceResource(location)并选择正确的模板字符串。

public void someService(Company company, Location location) {
    String name = company.getName();
    String info = company.getInfo();
    ....

    String resourcee = chooseResourceTemplate(location);

    String body = templateEngine.process(resource, content);
    ...
    //do something else and send the email
  }

templateEngine被注入@Qualifier private TemplateEngine templateEngine;

更新: 里面EmailService我有以下方法:

public void setTemplateEngine(TemplateEngine templateEngine) {
    this.templateEngine = templateEngine;
  }

我通过以下方式注入它:

 @Autowired
  @Qualifier("textTemplateEngine")
  private TemplateEngine templateEngine;

这里面EmailServiceTest曾经是我的 setUp():

@Before
  public void setup() {
    ThymeleafConfig tc = new ThymeleafConfig();
    templateEngine = tc.templateEngine();

    MockitoAnnotations.initMocks(this);
    emailService.setTemplateEngine(templateEngine);
  }

是的,我知道这templateEngine不是一个模拟,而是一个实际的对象,因此在线错误verify(templateEngine).process("templateEU", any(Content.class));。但是当我将其更改为模拟时,我得到NullpointerException.

更新结束

在我的测试中,我想测试当位置是欧洲时它会处理templateEU,当位置是美国时它会处理templateEU

我尝试了以下方法:

@Test
  public void shouldCallTemplateEngineWithEuropeTemplate(){
    location = Location.EUROPE;

    //throws null pointer exception
    emailService.sendEmail(any(Person.class), location);

    verify(templateEngine).process("templateEU", any(Content.class));
  }

但它抱怨我在嘲笑Person参数。在这个特定的测试中,我不关心Person我发送的是哪个对象,我只关心Location枚举。

标签: javaunit-testingmockingmockito

解决方案


在对模拟依赖项安排或断言成员调用时使用参数匹配器。

在执行被测成员时,它们不会作为参数使用/传递,实际上会传递类型的默认值,在这种情况下为null。因此,当

String name = person.getName();

叫做。

相反,创建参数的实例并将其传递给被测对象。

//Arrange
location = Location.EUROPE;
Person person = new Person();

//Act
emailService.sendEmail(person, location);

//Assert
//...

或者只是模拟类并传递它以避免空引用错误

//Arrange
location = Location.EUROPE;
Person person = mock(Person.class);

//Act
emailService.sendEmail(person, location);

//Assert
//...

确保设置任何成员调用Person,如果未配置会导致问题。

至于模板问题,您应该模拟模板,以便单元测试真正成为一个孤立的测试。

@Before
public void setup() {    
    templateEngine = mock(TemplateEngine.class); //Use a mock

    MockitoAnnotations.initMocks(this);
    emailService.setTemplateEngine(templateEngine);
}

verify(templateEngine).process("templateEU", any(Content.class));

行为符合预期。


推荐阅读