2017-02-16 167 views
0

經過近8年的時間,我不得不粉碎我的Spring知識,只要我不必編寫單元測試,事情就很好。我有以下的單元測試將測試我的服務之一,當我試圖運行它,它會失敗的:運行單元測試時出現彈簧啓動錯誤

org.springframework.beans.factory.UnsatisfiedDependencyException 

,這是不能夠解決eMailNotificationService服務!

因此,這裏是我的單元測試:

@ActiveProfiles("test") 
@ComponentScan(basePackages = {"com.middleware.service.email", "it.ozimov.springboot.templating.mail"}) 
@RunWith(SpringRunner.class) 
public class EMailNotificationServiceTest { 

    @Autowired() 
    private EMailNotificationService eMailNotificationService; 

    @MockBean(name = "emailService") 
    private EmailService emailService; 

    @Test 
    public void sendResetPasswordEMailNotification() { 

     System.out.println(eMailNotificationService); 

     // TODO: complete the test 
    } 
} 

的EMailNotificationService是下面這在com.middleware.service.email包中定義:

@Service() 
@Scope("singleton") 
public class EMailNotificationService { 

    private static Log logger = LogFactory.getLog(EMailNotificationService.class); 

    @Value("${service.email.sender}") 
    String senderEMail; 

    @Value("${service.email.sender.name}") 
    String senderName; 

    @Value("${service.email.resetPassword.link}") 
    String resetPasswordLink; 

    @Autowired 
    public EmailService emailService; 

    public void sendResetPasswordEMail(List<EMailUser> userList) { 
     List<String> allEMails = userList.stream() 
            .map(EMailUser::getUserEMail) 
            .collect(Collectors.toList()); 
     userList.stream().forEach(emailUser -> { 
      final Email email; 
      try { 
       email = DefaultEmail.builder() 
         .from(new InternetAddress(senderEMail, senderName)) 
         .to(Lists.newArrayList(new InternetAddress(emailUser.getUserEMail(), emailUser.getUserName()))) 
         .subject("Reset Password") 
         .body("")//Empty body 
         .encoding(String.valueOf(Charset.forName("UTF-8"))).build(); 

       // Defining the model object for the given Freemarker template 
       final Map<String, Object> modelObject = new HashMap<>(); 
       modelObject.put("name", emailUser.getUserName()); 
       modelObject.put("link", resetPasswordLink); 

       emailService.send(email, "resetPasswordEMailTemplate.ftl", modelObject); 
      } catch (UnsupportedEncodingException | CannotSendEmailException ex) { 
       logger.error("error when sending reset password EMail to users " + allEMails, ex); 
      } 
     }); 
    } 
} 

我怎樣寫我的單元測試,使我的服務注入/自動裝配?

+0

是有可能,是不是爲您的配置文件創建這個bean '測試'? – wawek

回答

0

您在測試中使用了一個@MockBean註釋,它附帶了一個彈簧引導測試。因此,如果您依賴的是spring-boot-test提供的功能,則必須使用@SpringBootTest註釋標記測試(在這種情況下,您還可以移除@ComponentScan註釋)。因此,spring會正確地模擬你的依賴關係(EmailService)並且會爲你提供EmailNotificationService bean。

關於春天開機測試的更多信息,可能是有用的可以自己參考文檔中找到:https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html

更新:

這樣的測試帶來了整個背景下可能是不必要的和適合寧可集成測試而不是單元測試。對於'純粹'單元測試,你可以忘記你正在測試spring服務,並將你的類作爲POJO處理。在這種情況下,你可以使用Mockito來嘲笑你的依賴(這是btw自帶的spring-boot-test)。您可以通過以下方式重寫代碼:

@RunWith(MockitoJUnitRunner.class) 
public class EMailNotificationServiceTest { 

    @InjectMocks 
    private EmailNotService eMailNotificationService; 

    @Mock 
    private EmailService emailService; 

    @Before 
    public void setup() { 
     eMailNotificationService.setSenderEMail("myemail"); 
     // set other @Value fields 
    } 

    @Test 
    public void sendResetPasswordEMailNotification() { 
     System.out.println(eMailNotificationService); 
     // TODO: complete the test 
    } 

} 
+0

使用@SpringBootTest註解將加載整個我的應用程序,從創建Hibernate映射,實例化其他服務等等,我實際上不需要。此電子郵件服務完全隔離編寫。它沒有任何依賴或任何休眠。那麼我怎麼才能實例化這個服務並測試它呢? – sparkr

+0

關閉,但還不夠!我仍然需要其他字段的值,如senderEMail,senderName,resetPasswordLink。那麼我也嘲笑這一點嗎?這對於我的私人領域嘲笑價值已經有點噁心了。 – sparkr

+0

@sparkr在'@SpringBootTest'中可以設置配置類(通過arg classes =「your.class」)。在那個類中,標記爲'@ TestConfiguration',你可以通過'@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class,...})排除所有不需要的配置' – rvit34

0

我更喜歡使用這種結構:

public static void manuallyInject(String fieldName, Object instance, Object targetObject) 
     throws NoSuchFieldException, IllegalAccessException { 
    Field field = instance.getClass().getDeclaredField(fieldName); 
    field.setAccessible(true); 
    field.set(instance, targetObject); 
} 

你的情況:manuallyInject("eMailNotificationService", emailService, eMailNotificationService)

相關問題