Obiekt przekazywany w teście controllera jest nullem

0

Witam,
dlaczego w klasie PhoneNumberControllerTest obiekt przekazywany w .content(new Gson().toJson(phoneNumberPL))) jest nullem ?

Bean

@Bean(name = "PNCorrectPL")
@Profile("test")
public PhoneNumber CretePNCorrectPL() {    
  PhoneNumber phoneNumber = new PhoneNumber("1234567890");    
  phoneNumber.setRegion("PL");    
  return phoneNumber;
}

PhoneNumberControllerTest.java

@WebMvcTest(PhoneNumberController.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class PhoneNumberControllerTest {    
  
  @Qualifier("PNCorrectPL")    
  @Autowired    
  PhoneNumber phoneNumberPL;

  
  private PhoneNumberController phoneNumberController;
  
  @BeforeAll 
  void init(){    
    this.phoneNumberService = new PhoneNumberService();    
    this.regionService = new RegionService();    
    this.phoneNumberController = new PhoneNumberController(phoneNumberService, regionService, phoneNumberPL);     
  }
  
  @Test
  void createModel() {    
    PhoneNumber result = phoneNumberController.createModel();    
    assertEquals(phoneNumberDefault, result);
  }
  
  @Test
  void submitNumbers() throws Exception {    
    mockMvc.perform(MockMvcRequestBuilders.post("/validate_phonenumber")                    
      .contentType(MediaType.APPLICATION_JSON)                    
      //.requestAttr("voivodeship", 10)                   
      .content(new Gson().toJson(phoneNumberPL)))            
      .andExpect(model().attribute("phoneNumber", phoneNumberPL))            
      .andExpect(model().hasNoErrors())            
      .andExpect(view().name("/phonenumber_validated"))           
      .andExpect(status().isOk());
  }}

PhoneNumberController.class

@Controller
public class PhoneNumberController {   

  @Qualifier("PNDefault")    
  @Autowired    
  PhoneNumber phoneNumber;
  
  @Autowired
  private final PhoneNumberService phoneNumberService;
  
  private final RegionService regionService;
  
  
  public PhoneNumberController(PhoneNumberService phoneNumberService, RegionService regionService, @Qualifier("PNDefault") PhoneNumber phoneNumber) {    
  this.phoneNumberService = phoneNumberService;
  this.regionService = regionService;
  this.phoneNumber = phoneNumber;
  }
  
   @ModelAttribute("phoneNumber")    
   public PhoneNumber createModel() {        
   return phoneNumber;    
   }    
   
   @PostMapping("/validate_phonenumber")    
   public String submitNumbers(@Valid @ModelAttribute("phoneNumber") PhoneNumber phoneNumber, BindingResult bindingResult) throws NumberParseException {        
       
   
   if (bindingResult.hasErrors()) {            
   System.out.println("There were errors");            
   bindingResult.getAllErrors().forEach(error -> {                
   System.out.println(error.getObjectName() + " " + error.getDefaultMessage());            
   });            
   return "phonenumber_form";        
   } 
   else {            
   phoneNumber.setCountry_code(phoneNumberService.getCountryCode(phoneNumber.getRegion()));                     
   phoneNumberService.Validate(phoneNumber);            
   return "/phonenumber_validated";        
   }    
 }}
0

To są testy... sam tworzysz obiekt kontrolera, w testach nie działa DI Springa :)

0

Dlaczego miałby nie być nullem, skoro go nie inicjalizujesz? Albo go utwórz jak człowiek, albo kombinuj https://www.baeldung.com/spring-boot-testing

0
piotrpo napisał(a):

Dlaczego miałby nie być nullem, skoro go nie inicjalizujesz? Albo go utwórz jak człowiek, albo kombinuj https://www.baeldung.com/spring-boot-testing

@Qualifier("PNCorrectPL")    
@Autowired    
PhoneNumber phoneNumberPL;

W np. tym teście jest wszystko ok:

@Test
void createModel() {    
PhoneNumber result = phoneNumberController.createModel();    
assertEquals(phoneNumberPL, result);}
0

@Autowired to nie jest jakaś magia, która powoduje, że jakiś obiekt sam się gdzieś stworzy i wstrzyknie się we właściwe miejsce. To jedynie poinformowanie kontenera IoC, że ma sobie poszukać miejsca gdzie jest napisane new i wrzucenie utworzonego w ten sposób obiektu we właściwe miejsce. Coś jeszcze musi ten kontener poinformować, że ma zacząć pracować. W aplikacji robie to w zagmatwany sposób SpringApplication.run(HelloApplication.class, args); Po tym kawałku kodu aplikacja wystartuje, utworzy springowy context, ten kontekst sprawdzi sobie gdzie są adnotacje @Component i pochodne, gdzie są ich zależności, potworzy to wszystko i poskłąda do kupy. W tym teście nie masz utworzenie kontekstu springboota, więc cała ta "magia" się nie dzieje.Poszukaj sobie informacji o testach integracyjnych Springa. Masz tam możliwość postawienia całego tego syfu i faktyczne, wtedy ci się zależności wstrzykną.
W tym teście:

Amakesh napisał(a):
@Test
void createModel() {    
PhoneNumber result = phoneNumberController.createModel();    
assertEquals(phoneNumberPL, result);}

Masz przecież gdzieś zainicjalizowany phoneNumberController, na którym wykonujesz createModel() a wynik przypisujesz do zmiennej.

0
Amakesh napisał(a):
piotrpo napisał(a):

Dlaczego miałby nie być nullem, skoro go nie inicjalizujesz? Albo go utwórz jak człowiek, albo kombinuj https://www.baeldung.com/spring-boot-testing

@Qualifier("PNCorrectPL")    
@Autowired    
PhoneNumber phoneNumberPL;

W np. tym teście jest wszystko ok:

@Test
void createModel() {    
PhoneNumber result = phoneNumberController.createModel();    
assertEquals(phoneNumberPL, result);}

No jest ok, bo oba PhoneNumbery są nullem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1