2017-10-14 4 views
2

Ich habe einen @ Service, den ich versuche, in einem Unit Test zu verspotten, aber ich bekomme bisher einen Null-Wert. In der Anwendungsklasse gebe ich an, was die scanBasePackages sind. Muss ich das anders machen? Vielen Dank.@Service im Komponententest in SpringBoot-Projekt nicht injizieren

Dies ist meine Service-Klasse, die eine Schnittstelle implementiert:

@Service 
public class DeviceService implements DeviceServiceDao { 

private List<Device> devices; 

@Override 
public List<Device> getDevices(long homeId) { 
    return devices; 
} 

} 

Das ist mein Gerät zu testen.

public class SmartHomeControllerTest { 

    private RestTemplate restTemplate = new RestTemplate(); 
    private static final String BASE_URL = “..”; 

    @Mock 
    private DeviceService deviceService; 

@Test 
public void getHomeRegisteredDevices() throws Exception { 

    Device activeDevice = new DeviceBuilder() 
      .getActiveDevice(true) 
      .getName("Alexa") 
      .getDeviceId(1) 
      .getHomeId(1) 
      .build(); 
    Device inativeDevice = new DeviceBuilder() 
      .getInactiveDevice(false) 
      .getName("Heater") 
      .getDeviceId(2) 
      .getHomeId(1) 
      .build(); 

    UriComponentsBuilder builder = UriComponentsBuilder 
      .fromUriString(BASE_URL + "/1/devices"); 

    List response = restTemplate.getForObject(builder.toUriString(), List.class); 

    verify(deviceService, times(1)).getDevices(1); 
    verifyNoMoreInteractions(deviceService); 
} 

Antwort

0

Sie sollten Ihren Test mit Federverschluß Läufer

1

Sie führen eine Federtestläufer verwenden, wenn Sie einen Feder Kontext während der Tests die Ausführung laden und verwenden möchten.
Sie geben keinen Runner an, daher verwendet er standardmäßig den Runner Ihrer Test-API. Hier ist wahrscheinlich JUnit oder TestNG (der Runner verwendet hängt von der @Test Annotation angegeben).
Außerdem nach der Logik Ihres Tests, möchten Sie die „echten“ REST Dienst aufzurufen:

List response = restTemplate.getForObject(builder.toUriString(), 
List.class); 

es zu erreichen, sollten Sie den Frühling Kontext laden und die Feder-Boot-Container laden, indem Sie die Kommentierung Test mit @SpringBootTest.

Wenn Sie einen Spring Boot-Kontext verwenden, um die Abhängigkeit im Spring-Kontext nachzuahmen, dürfen Sie nicht @Mock von Mockito, sondern @MockBean von Spring Boot verwenden.
Um den Unterschied zwischen den beiden zu verstehen, können Sie sich auf diese question beziehen.

Beachten Sie, dass bei Verwendung der @SpringBootTest Annotation eine TestRestTemplate automatisch verfügbar ist und in Ihren Test automatisch eingefügt werden kann.
Aber Vorsicht, das ist fehlertolerant. Es kann passend oder nicht entsprechend Ihren Tests sein.

So könnte Ihr Code wie folgt aussehen:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) 
public class SmartHomeControllerTest { 

    private static final String BASE_URL = “..”; 

    @Autowired 
    private TestRestTemplate restTemplate; 

    @MockBean 
    private DeviceService deviceService; 

    @Test 
    public void getHomeRegisteredDevices() throws Exception {   
     ... 
    } 

Als Randbemerkung, vermeiden roh Typ als List verwenden, aber generische Art begünstigen.

+0

ich diesen Teil geändert haben. Ich konzentrierte mich auf das Injektionsproblem. Aber du hast wahrscheinlich Recht. Ich stelle auch fest, dass das OP keine Aussage über die abgerufene "Liste" macht. – davidxxx

+0

Ich habe die SpringBootTest- und MockBean-Annotation hinzugefügt, aber jetzt bekomme ich einen Null-Kontext: "Verursacht von: java.lang.IllegalArgumentException: Kann keinen ApplicationContext mit einem NULL 'contextLoader' laden. Erwägen Sie Ihre Testklasse mit @ContextConfiguration oder @ContextHierarchy . " – user1140656

0

Ich habe es herausgefunden, ich benutze Mockito und benutze das, um meine Testklasse zu kommentieren. Dies ermöglichte es mir, die Serviceklasse, die ich benutzen möchte, zu verspotten.

@RunWith(MockitoJUnitRunner.class) 
public class SmartHomeControllerTest {.. 
    @Mock 
    private DeviceService deviceService; 
    } 
0

mit @InjectMock Versuchen statt @Mock

Verwandte Themen