Standardmethode:
@RestController
public class Main {
UserService userService;
public Main(){
userService = new UserServiceImpl();
}
@GetMapping("/")
public String index(){
return userService.print("Example test");
}
}
Schnittstelle für Benutzerdienste:
public interface UserService {
String print(String text);
}
UserServiceImpl-Klasse:
public class UserServiceImpl implements UserService {
@Override
public String print(String text) {
return text + " UserServiceImpl";
}
}
Sortie : 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).
Werfen wir nun einen Blick auf SpringBoot Dependency Injection, ein schönes Beispiel für lose Kopplung:
Die Schnittstelle bleibt unverändert,
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";
}
}
Sortie : Example test UserServiceImpl
und jetzt ist es einfach, Tests 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 zeigte @Autowired
Annotation auf Konstruktor, aber es kann auch auf Setter oder Feld verwendet werden.