Das Team, dem ich angehöre, hat die Regel, dass ich bei Problemen einen Testcode schreibe, ihn reproduziere (überprüfen Sie den roten Balken) und ihn dann behebe. Neulich gab es ein Problem, dass die Transaktionskontrolle fehlte, also habe ich versucht, einen Testcode zu schreiben, aber da ich verwirrt war, werde ich ihn organisieren und veröffentlichen. Der Testcode ist auf Github (https://github.com/shimi58/transactiontest) aufgeführt. Bitte beziehen Sie sich darauf.
Die auf Eclipse basierende Umgebung ist wie folgt. Ich habe ein Gradle-Projekt erstellt und es durch den Pfad geleitet.
Umgebung | Ausführung |
---|---|
Java | 1.8 |
SpringBoot | 2.2.6 |
MyBatis | 2.1.0 |
H2 | PostgresqlMode |
Junit | 5(Jupiter) |
Registrieren Sie Mitarbeiterinformationen (Name, Telefonnummer, E-Mail-Adresse) und aktualisieren Sie die Nummer in der Mitarbeitertabelle auf die Statustabelle. Es ist eine Beispielquelle wie.
/**
* Mitarbeiterservice
*/
@Service
public class EmployeeService {
@Autowired
EmployeeRepository employeeRepository;
/**
* Mitarbeiterregistrierung
*/
@Transactional // ← Dies war undicht
public EmployeeNumber register(Employee employee) {
employeeRepository.registerEmployee(employee);
Employees employees = employeeRepository.findEmployees();
EmployeeNumber employeeNumber = employees.number();
employeeRepository.registerNumber(employeeNumber);
return employeeNumber;
}
}
In dieser Beispielquelle wird sie als Mitarbeitertabelle → Statustabelle aktualisiert. Wenn die Transaktion jedoch nicht wirksam ist und die Aktualisierung der Statustabelle fehlschlägt, wird sie in der in der Mitarbeitertabelle enthaltenen Nummer- und Statustabelle beibehalten. Die Anzahl der Fälle ist inkonsistent.
Die Controller-Klasse wird übrigens später erwähnt, wenn der Testcode erklärt wird.
/**
* Mitarbeiter-Controller
*/
@RestController
@RequestMapping("/employees")
public class EmployeesController {
@Autowired
EmployeeService employeeService;
/**
* Mitarbeiterregistrierung
*/
@RequestMapping(value = "/register", method = {RequestMethod.POST})
public String regist(@RequestBody Employee employee) {
EmployeeNumber employeeNumber = new EmployeeNumber(0);
try {
employeeNumber = employeeService.register(employee);
} catch (Exception e) {
System.out.println ("Verarbeitungsfehler");
}
return employeeNumber.toString();
}
}
Verwenden Sie ** @SpyBean **.
SpyBean ist eine Funktion von Spring Boot und ein Suguremono, das nur einen Teil der Verarbeitung der Klasse macht, die Sie in Mock testen möchten. Im Fall dieser Beispielquelle verspotten Sie das EmployeeRepository mit SpyBean und
--registerEmployee: Mitarbeiterregistrierungsprozess → Normale Implementierung --findEmployees: Verarbeitung der Mitarbeitertabellenanzahl → Normale Ausführung --registerNumber: Aktualisierung der Statustabelle → Fehler aufgetreten
Ich möchte eine solche Situation schaffen.
Der Test wird ausgeführt, indem die Controller-Klasse als SpringBootTest aufgerufen wird. Die Controller-Klasse ruft die oben genannte Serviceklasse auf.
@SpringBootTest
public class EmployeesControllerTransactionTest {
MockMvc mockMvc;
@Autowired
private ObjectMapper mapper;
@Autowired
private EmployeesController employeesController;
// Ziel verspotten
@SpyBean
private EmployeeRepository employeeRepository;
/**
* Transaktionstest
*
* Wenn beim Aktualisieren der Anzahl der Mitarbeiter nach der Registrierung der Mitarbeiterinformationen in der Tabelle "Mitarbeiter" ein Fehler auftritt, <br>
* Stellen Sie sicher, dass Sie die Registrierung von Mitarbeiterinformationen rückgängig machen
*
* @throws Exception
*/
@ParameterizedTest
@CsvSource ({"Takao Hibi, 123-4345-2352, [email protected], 3"})
public void testTransaction(String name, String phone, String mail, int expected)
throws Exception {
Employee employee = new Employee(name, phone, mail);
// Anfrage in Json-Format konvertieren
String json = mapper.writeValueAsString(employee);
// Fehler beim Auftreten
doThrow(new RuntimeException()).when(employeeRepository)
.registerNumber(Mockito.any(EmployeeNumber.class));
this.mockMvc = MockMvcBuilders.standaloneSetup(employeesController).build();
// Anfrage ausgeben
MvcResult result = mockMvc.perform(
post("/employees/register").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isOk()).andReturn();
String response = result.getResponse().getContentAsString();
Employees employees = employeeRepository.findEmployees();
System.out.println(response);
System.out.println(employees.toString());
EmployeeNumber actual = employees.number();
// Da es zurückgesetzt wird, überprüfen Sie vor der Registrierung, ob es sich im Status 3 befindet
assertEquals(expected, actual.getValue().intValue());
}
@SpringBootTest
public class EmployeesControllerTransactionTest {
Es ist unverzichtbar, da es nur dann DI wird, wenn SpringBootTest angehängt ist.
@SpyBean
private EmployeeRepository employeeRepository;
Deklarieren Sie das zu verspottende Repository.
@ParameterizedTest
@CsvSource ({"Takao Hibi, 123-4345-2352, [email protected], 3"})
Obwohl dies nichts mit diesem Artikel zu tun hat, können Sie mit CsvSource Variationstests mit einer Methode durchführen. Ich hatte eine lange Geschichte mit Junit4 und war beeindruckt, als mir klar wurde, dass ich das schaffen kann. Der Name wurde übrigens von Amazing Name Generator entlehnt. Es ist eine bequeme Welt geworden. (Mehr irrelevant.)
// Fehler beim Auftreten
doThrow(new RuntimeException()).when(employeeRepository)
.registerNumber(Mockito.any(EmployeeNumber.class));
Hier wird deklariert, dass bei der Verarbeitung von registerNumber eine RuntimeException generiert wird.
this.mockMvc = MockMvcBuilders.standaloneSetup(employeesController).build();
Dohamari Punkt ①. Wenn Sie StandaloneSetup nicht ausführen, wird mockMvc mit nullpo gelöscht.
MvcResult result = mockMvc.perform(
post("/employees/register").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isOk()).andReturn();
Dohamari Punkt ②. Wenn es nicht status (). IsOk () ist, wird es wegfliegen (devac wird nicht zurückgegeben). Ich war eine Stunde lang besorgt, als die Post-URL falsch war und 404 zurückgegeben wurde und warum die Debug-Antwort nicht auftrat.
Als ich den Testcode ausführte, stellte sich heraus, dass es sich um einen wunderbaren grünen Balken handelte!
Übrigens, wenn Sie @Transactional in der Serviceklasse entfernen,
Ja, es ist ein roter Balken. Wenn sich die Anzahl der Elemente in der Mitarbeitertabelle um eins unterscheidet, tritt ein Bestätigungsfehler auf und die Transaktion kann bestätigt werden.
Ich werde alleine zurückblicken.
Recommended Posts