2015-11-10 24 views
0

我想單元測試一個Spring引導控制器,並且我的@Autowired字段之一返回null。如何在嘲笑另一個字段的同時自動裝載真實實現的字段?

我在這個控制器配備了兩個自動連接字段:

public class UserProfileController{ 

@Autowired 
private UserProfileService profileService; 

@Autowired 
private IDataValidator dataValidatorImpl; 

我的測試類如下:

@RunWith(SpringJUnit4ClassRunner.class) 
@WebIntegrationTest 
@SpringApplicationConfiguration(classes = UserProfileServiceApplication.class) 
public class ControllerTest { 

private MockMvc mockMvc; 

@Mock 
UserProfileService profileServiceMock; 

@Autowired 
ApplicationContext actx; 

@InjectMocks 
private UserProfileController profileController; 

@Before 
public void setup() { 
// Process mock annotations 
String[] asdf = actx.getBeanDefinitionNames(); 
for (int i = 0; i < asdf.length; i++){ 
System.out.println(asdf[i]); 
} 

MockitoAnnotations.initMocks(this); 

// Setup Spring test in standalone mode 
this.mockMvc = MockMvcBuilders.standaloneSetup(profileController).build(); 

} 

/** 
* All this does is verify that we return the correct datatype and HTTP status 
* @throws Exception 
*/ 
@Test 
public void testGetProfileSuccess() throws Exception { 
Mockito.when(profileServiceMock.getProfile(Mockito.any(HashMap.class))).thenReturn(new HashMap<String, Object>()); 

mockMvc.perform(get("http://localhost:8095/UserName?tenantId=tenant1")) 
.andExpect(status().isOk()) 
.andExpect(content().contentType(TestUtil.APPLICATION_JSON_UTF8)); 

//verify profileService was only used once 
Mockito.verify(profileServiceMock, Mockito.times(1)).getProfile(Mockito.any(HashMap.class)); 

//verify we're done interacting with profile service 
Mockito.verifyNoMoreInteractions(profileServiceMock); 
} 

如果我離開IDataValidator不變的測試類,它出現空和我得到一個NPE。如果我使用DataValidatorImpl,它無法從Spring環境中找到它需要工作的屬性。

我該如何讓IDataValidator自動裝載自身並維護它的彈簧環境上下文,就像我正常運行應用程序一樣?

當我在我的@Before setup()方法中打印所有bean時,我可以在列表中看到DataValidationImpl。

+0

你在哪裏嘲諷'IDataValidator'? – jny

+0

我試圖不嘲笑它。當我使用'@ spy'註釋時,請參閱上面的編輯。 – lp1776

回答

0

好吧,我發誓,我這樣做是第一次,但試圖重新拋出JNY錯誤時,它實際工作。

我的解決方案是通過@Spy註釋注入並從我的@Before安裝方法中獲得來自ApplicationContext的bean。

public class ControllerTest { 

private MockMvc mockMvc; 

@Mock 
UserProfileService profileServiceMock; 

@Spy 
IDataValidator dataValidator; 

@Autowired 
ApplicationContext actx; 

@InjectMocks 
private UserProfileController profileController; 

@Before 
public void setup() { 

dataValidator = (IDataValidator) actx.getBean("dataValidatorImpl"); 

MockitoAnnotations.initMocks(this); 

// Setup Spring test in standalone mode 
this.mockMvc = MockMvcBuilders.standaloneSetup(profileController).build(); 

} 
0

如果我理解正確,你想要注入UserProfileController真正的驗證和模擬服務。

在這種情況下,我建議使用@ContextConfiguration註釋,它允許在測試中配置上下文。你需要創建一個配置類:

@RunWith(SpringJUnit4ClassRunner.class) 
@WebIntegrationTest 
@SpringApplicationConfiguration(classes = UserProfileServiceApplication.class) 
public class ControllerTest { 

private MockMvc mockMvc; 

@Mock 
UserProfileService profileServiceMock; 

@Autowired 
ApplicationContext actx; 

//comment this line out 
//@InjectMocks 
@Autowired 
private UserProfileController profileController; 

@Before 
public void setup() { 
// Process mock annotations 
String[] asdf = actx.getBeanDefinitionNames(); 
for (int i = 0; i < asdf.length; i++){ 
System.out.println(asdf[i]); 
} 

//comment this line out 
//MockitoAnnotations.initMocks(this); 

    @Configuration 
    public static class Config { 

    //wire validator - if it is not wired by other configurations 
    @Bean 
    Validator validator() { 
     return new Validaor(); 
    } 

    //wire mock service 
    @Bean 
    public UserProfileService profileService() { 
     return mock(UserProfileService.class); 
    } 
} 
1

當你嘲笑與

MockMvcBuilders.standaloneSetup(profileController).build(); 

控制器被替換的背景下,您的控制器。由於您沒有在其中注入IDataValidator,因此它爲空。

最簡單的解決方案是將真正的IDataValidator自動裝配到您的測試類中並將其注入到控制器中。

在你的控制器:

public class UserProfileController{ 

private UserProfileService profileService; 
private IDataValidator dataValidatorImpl; 

@Autowired 
public UserProfileController(UserProfileService profileService, IDataValidator dataValidatorImpl) { 
    this.profileService = profileService; 
    this.dataValidatorImpl = dataValidatorImpl; 
} 

並在測試:

@RunWith(SpringJUnit4ClassRunner.class) 
@WebIntegrationTest 
@SpringApplicationConfiguration(classes = UserProfileServiceApplication.class) 
public class ControllerTest { 

private MockMvc mockMvc; 

private UserProfileService profileService; 

@Autowired 
private IDataValidator dataValidator; 

@Before 
public void setup() { 
    UserProfileService profileService = Mockito.mock(UserProfileService.class); 
    UserProfileController controller = new UserProfileController(profileService, dataValidator); 

    // Setup Spring test in standalone mode 
    this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); 

} 

} 
相關問題