在Spring4中使用带有特定模拟依赖的自动连接依赖



我有注册和登录的休息资源。都在控制器类中。控制器类依赖于具有业务逻辑的服务类。服务类有更多的依赖项。因为我使用嵌入式数据库进行测试,所以我想使用我的应用程序的真正依赖关系,而不是用@injectmock @mock之类的东西来模拟它们。只有一种依赖我不得不嘲笑。它是在注册过程后发送电子邮件的依赖项。如何编写测试用例与@autowired功能和一个特定的模拟依赖于电子邮件通知?

    @Controller
    public class AccountCommandsController {
        @Autowired
        private LogoutService service;
        @RequestMapping(value = "/rest/login", method = RequestMethod.POST)
        public ResponseEntity login(@RequestBody Account account) {
            AccountLoginEvent accountLoginEvent = service.loginAccount(new RequestAccountLoginEvent(account.getEmailAddress(), account.getPassword()));
            if (accountLoginEvent.isLoginGranted()) {
                return new ResponseEntity(HttpStatus.ACCEPTED);
            } else {
                return new ResponseEntity(HttpStatus.UNAUTHORIZED);
            }
        }
        @RequestMapping(value = "/rest/signup", method = RequestMethod.POST)
        public ResponseEntity signup(@RequestBody Account account) {
            AccountSignupEvent signedupEvent = service.signupAccount(new RequestAccountSignupEvent(account.getEmailAddress(), account.getPassword()));
            if (signedupEvent.isSignupSuccess()) {

        return new ResponseEntity(HttpStatus.ACCEPTED);
        } else if (signedupEvent.isDuplicateEmailAddress()) {
            return new ResponseEntity(HttpStatus.CONFLICT);
        } else if (signedupEvent.isNoSignupMailSent()) {
            return new ResponseEntity(HttpStatus.SERVICE_UNAVAILABLE);
        } else {
            return new ResponseEntity(HttpStatus.FORBIDDEN);
            }
        }
    }
    @Service
    public class LogoutService {
    @Autowired
    private AccountsRepository accountsRepository;
    @Autowired
    private MailService mailService;
    @Autowired
    private HashService hashService;
    public AccountSignupEvent signupAccount(RequestAccountSignupEvent signupEvent) {
        if (accountsRepository.existEmailAddress(signupEvent.getEmailAddress())) {
            return AccountSignupEvent.duplicateEmailAddress();
        }
        Account newAccount = new Account();
        newAccount.setCreated(new Date());
        newAccount.setModified(new Date());
        newAccount.setEmailAddress(signupEvent.getEmailAddress());
        newAccount.setPassword(signupEvent.getPassword());
        newAccount.setVerificationHash(hashService.getUniqueVerificationHash());
        SignupMailEvent mailSentEvent = mailService.sendSignupMail(new RequestSignupMailEvent(newAccount));
        if (!mailSentEvent.isMailSent()) {
            return AccountSignupEvent.noMailSent();
        }
        Account persistedAccount = accountsRepository.persist(newAccount);
        return AccountSignupEvent.accountCreated(persistedAccount);
    }
    public AccountLoginEvent loginAccount(RequestAccountLoginEvent loginEvent) {
        if (accountsRepository.existLogin(loginEvent.getEmailAddress(), loginEvent.getPassword())) {
            return AccountLoginEvent.granted();
        }
        return AccountLoginEvent.denied();
        }
    }
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = TestConfiguration.class)
    @Transactional
    @TransactionConfiguration(defaultRollback = true)
    public class LogoutTest {
        private MockMvc mockMvc;
        @Autowired
        private AccountCommandsController controller;
        @Before
        public void setup() {
            mockMvc = standaloneSetup(controller).build();
        }
        @Test
        public void signupNoMail() throws Exception {
            doReturn(AccountSignupEvent.noMailSent()).when(service).signupAccount(any(RequestAccountSignupEvent.class));
    //        when(controller.service.signupAccount(any(RequestAccountSignupEvent.class))).thenReturn(AccountSignupEvent.noMailSent());
            mockMvc.perform(post("/rest/signup")
                    .content(new Gson().toJson(new Account(UUID.randomUUID().toString(), UUID.randomUUID().toString())))
                    .contentType(MediaType.APPLICATION_JSON))
                    .andExpect(status().isServiceUnavailable());
        }
    }
我希望你能看到问题所在。每个依赖项都工作得很好,而不是mailservice。我不想使用@injectmock和@mock与MockitoAnnotations.initMocks(this);在我的测试文件中,由于需要为所有依赖项提供模拟。

如果你的依赖正在运行,并且你有一个定义了端点的配置类,你可以使用ConfigurableApplicationContext类,像这样:

 public class test {
     private static ConfigurableApplicationContext appContext;
     private LogoutService service;
     @AfterClass
     public static void destroy() {
       appContext.close();
     }
     @Before
     public void setup() {             
         appContext = new AnnotationConfigApplicationContext(YourClassConfig.class);
         service = appContext.getBean(LogoutService.class);        
     }
     @Test
     public void beansAreCreated() {
         assertNotNull(service);        
     }     
 }

或者你可以用一个配置类重写你的端点,你可以使用WireMock (http://wiremock.org)用真实的数据模拟你的依赖,这应该是这样的:

 public class test {
     @Rule
     public WireMockRule wireMockRule = new WireMockRule(15000);
     private static ConfigurableApplicationContext appContext;
     private LogoutService service;
     private static String serviceMockUrl;
     @AfterClass
     public static void destroy() {
       appContext.close();
     }
     @Before
     public void setup() {
         serviceMockUrl = "http://localhost:" + wireMockRule.port();
         appContext = new AnnotationConfigApplicationContext(TestConfig.class);
         stubFor(get(urlEqualTo("urlToRequest")).
            willReturn(aResponse().
                    withStatus(SC_OK).
                    withBody(createJsonArray("MapWithYourData").
                    withHeader("Content-Type", "application/json")));
         service = appContext.getBean(LogoutService.class);        
     }
     @Test
     public void beansAreCreated() {
         assertNotNull(service);        
    }       
    @Configuration
    static class TestConfig {
         @Bean
         public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
             return new PropertyPlaceholderConfigurer() {{
                 setProperties(new Properties() {{
                    setProperty("service.url", serviceMockUrl);
                 }});
             }};
         }
     }     
 }

你想做的是很容易实现使用Spring配置文件。

实现它的方法如下:

@Configuration
public class TestConfiguration {
   //this is the real mail service
   @Bean
   public MailService mailService() {
      return new MailService(); //or whatever other bean creation logic you are using
   }
   //whatever else
}
@Configuration
@Profile("mockMail")
public class MockMailServiceConfig {
   @Bean
   @Primary
   public MailService mockMailService() {
      return mock(MailService.class);
   }
}

你的测试类看起来像:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
@Transactional
@TransactionConfiguration(defaultRollback = true)
@ActiveProfiles("mockMail")
public class LogoutTest {
   //do your testing
}

注意MockMailServiceConfig@Primary的使用。我之所以选择这种方式,是因为它不需要您在其他地方介绍配置文件,如果您还没有使用它们的话。@Primary告诉spring,如果有多个可用的候选对象(在本例中有真实邮件服务和模拟服务),则使用特定的bean

相关内容

  • 没有找到相关文章

最新更新