Standard Weg:
@RestController
public class Main {
UserService userService;
public Main(){
userService = new UserServiceImpl();
}
@GetMapping("/")
public String index(){
return userService.print("Example test");
}
}
Benutzeroberfläche:
public interface UserService {
String print(String text);
}
UserServiceImpl-Klasse:
public class UserServiceImpl implements UserService {
@Override
public String print(String text) {
return text + " UserServiceImpl";
}
}
Ausgabe: Example test UserServiceImpl
Das ist ein großartiges Beispiel für eng gekoppelte Klassen, ein schlechtes Designbeispiel und es wird Probleme beim Testen geben (PowerMockito ist auch schlecht).
Schauen wir uns nun die SpringBoot-Abhängigkeitsinjektion an, ein schönes Beispiel für lose Kopplung:
Schnittstelle bleibt gleich,
Hauptklasse:
@RestController
public class Main {
UserService userService;
@Autowired
public Main(UserService userService){
this.userService = userService;
}
@GetMapping("/")
public String index(){
return userService.print("Example test");
}
}
ServiceUserImpl-Klasse:
@Component
public class UserServiceImpl implements UserService {
@Override
public String print(String text) {
return text + " UserServiceImpl";
}
}
Ausgabe: Example test UserServiceImpl
und jetzt ist es einfach, Test zu schreiben:
@RunWith(MockitoJUnitRunner.class)
public class MainTest {
@Mock
UserService userService;
@Test
public void indexTest() {
when(userService.print("Example test")).thenReturn("Example test UserServiceImpl");
String result = new Main(userService).index();
assertEquals(result, "Example test UserServiceImpl");
}
}
Ich habe @Autowired
Anmerkungen zum Konstruktor gezeigt, aber sie können auch für Setter oder Felder verwendet werden.