2017-12-21 10 views
2

私は、PatientRepositoryImplというJavaクラスを持っています。このクラスには、MySqlデータベースにデータを挿入、削除、または更新するいくつかのメソッドが含まれています。 私はこのクラスの単位テストも書きました。 テストのカバレッジをチェックすると、SQL Exceptionsを除き、ほとんどのコード行がカバレッジツールによって緑色にマークされていますが、59%しか得られません。 私はここに新しいです。誰かが私を助けることができれば、私はすべてのことを正しく行いました、非常に感謝したいと思います。データベースとやりとりするクラスのテストカバー率を上げるには?

私のリポジトリとテストのコードです。

public class PatientRepositoryMySqlImpl implements PatientRepository { 


private DatabaseConnection connection; 
private PatientGenerator patientGenerator; 


public PatientRepositoryMySqlImpl(DatabaseConnection connection, PatientGenerator patientGenerator) { 
    this.connection = connection; 
    this.patientGenerator = patientGenerator; 
} 

/* (non-Javadoc) 
* @see com.id.hl7sim.PatientRepository#insertPatient() 
*/ 
@Override 
public void insertPatient(Patient patient) { 
    if (!patient.isValid()) { 
     throw new IllegalArgumentException("Incomplete Patient"); 
    } else { 
     String insert = "INSERT INTO tbl_patient(lastname, firstname, gender, birthday) VALUES('" 
     + patient.getLastname() + "', '" + patient.getFirstname() + "', '" + patient.getGender() + "', '" 
     + patient.getBirthday().toString() + "');"; 
     try (Connection dbConnection = connection.getDBConnection(); 
      Statement statement = dbConnection.prepareStatement(insert)) { 
      statement.executeUpdate(insert); 
     } catch (SQLException e) { 
      System.out.println(e.getMessage()); 
     } 
    } 
} 

/* (non-Javadoc) 
* @see com.id.hl7sim.PatientRepository#insertListOfPatients() 
*/ 
@Override 
public void insertListOfPatients(List<Patient> allPatients) { 
    for (Patient patient : allPatients) { 
     insertPatient(patient); 
    } 
} 

/* (non-Javadoc) 
* @see com.id.hl7sim.PatientRepository#getRandomPatient() 
*/ 
@Override 
public Patient getRandomPatient() { 
    Patient patient = new Patient.Builder().build(); 
    String query = "SELECT * FROM tbl_patient ORDER BY RAND() LIMIT 1"; 
    try (Connection dbConnection = connection.getDBConnection(); 
     Statement statement = dbConnection.createStatement();) { 
     ResultSet rs = statement.executeQuery(query); 
     rs.next(); 
     setPatientBasicData(patient, rs); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
    return patient; 
} 

private void setPatientBasicData(Patient patient, ResultSet rs) { 
    try { 
     patient.setId(rs.getInt("id")); 
     patient.setLastname(rs.getString("lastname")); 
     patient.setFirstname(rs.getString("firstname")); 
     patient.setGender(rs.getString("gender")); 
     patient.setBirthday(parseBirthday(rs.getString("birthday"))); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
} 

public LocalDate parseBirthday(String birthday) { 
    LocalDate localDate = LocalDate.parse(birthday); 
    return localDate; 
} 

/* (non-Javadoc) 
* @see com.id.hl7sim.PatientRepository#admitRandomPatient() 
*/ 
@Override 
public Patient admitRandomPatient() { 
    Patient patient = getRandomPatient(); 
    patient.setDepartment(patientGenerator.getRandomDepartment()); 
    patient.setWard(patientGenerator.getRandomWard()); 
    patient.setAdmissionDateTime(LocalDateTime.now()); 
    patient.setStatus("I"); 
    String insert = "INSERT INTO tbl_inpatients(id, ward, department, admissionDate, patientStatus) VALUES('" 
        + patient.getId() + "', '" + patient.getWard() + "', '" + patient.getDepartment() + "', '" 
        + patient.getAdmissionDateTime().toString() + "', '" + patient.getStatus() + "')"; 
    try (Connection dbConnection = connection.getDBConnection(); 
     PreparedStatement statement = dbConnection.prepareStatement(insert)) { 
     statement.executeUpdate(insert, Statement.RETURN_GENERATED_KEYS); 
     ResultSet keys = statement.getGeneratedKeys(); 
     keys.next(); 
     patient.setCaseId(keys.getInt(1)); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
    return patient; 
} 

public Patient getRandomInpatient() { 
    Patient patient = new Patient.Builder().build(); 
    String query = "SELECT * FROM tbl_inpatients ip, tbl_patient p WHERE p.id = ip.id ORDER BY RAND() LIMIT 1"; 
    try (Connection dbConnection = connection.getDBConnection(); 
     Statement statement = dbConnection.createStatement();) { 
     ResultSet rs = statement.executeQuery(query); 
     rs.next(); 
     setPatientBasicData(patient, rs); 
     setPatientCaseData(patient, rs); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
    return patient; 
} 

public void setPatientCaseData(Patient patient, ResultSet rs) { 
    try { 
     patient.setWard(rs.getString("ward")); 
     patient.setDepartment(rs.getString("department")); 
     patient.setAdmissionDateTime(parseLocalDateTime(rs.getString("admissionDate"))); 
     patient.setStatus(rs.getString("patientStatus")); 
     patient.setCaseId(rs.getInt("case")); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
} 

public LocalDateTime parseLocalDateTime(String localdatetime) { 
    localdatetime = localdatetime.replace("T", ""); 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss.SSS"); 
    LocalDateTime formattedLocalDateTime = LocalDateTime.parse(localdatetime, formatter); 
    return formattedLocalDateTime; 
} 

/* (non-Javadoc) 
* @see com.id.hl7sim.PatientRepository#transferRandomPatient() 
*/ 
@Override 
public Patient transferRandomPatient() { 
    Patient patient = getRandomInpatient(); 
    patient.setPriorWard(patient.getWard()); 
    patient.setPriorDepartment(patient.getPriorDepartment()); 
    patient.setDepartment(patientGenerator.getRandomDepartment()); 
    patient.setWard(patientGenerator.getRandomWard()); 
    String update = "UPDATE tbl_inpatients SET ward='" + patient.getWard() + "', department='" 
      + patient.getDepartment() + "' WHERE id='" + patient.getId() + "'"; 
    try (Connection dbConnection = connection.getDBConnection(); 
     Statement statement = dbConnection.prepareStatement(update)) { 
     statement.executeUpdate(update); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
    return patient; 
} 

/* (non-Javadoc) 
* @see com.id.hl7sim.PatientRepository#dischargeRandomPatient() 
*/ 
@Override 
public Patient dischargeRandomPatient() { 
    Patient patient = getRandomInpatient(); 
    patient.setDischargeDateTime(LocalDateTime.now()); 
    insertFormerPatient(patient); 
    String delete = "DELETE FROM tbl_inpatients WHERE `case`=" + patient.getCaseId(); 
    try (Connection dbConnection = connection.getDBConnection(); 
     Statement statement = dbConnection.prepareStatement(delete)) { 
     statement.executeUpdate(delete); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
    return patient; 
} 

public void insertFormerPatient(Patient patient) { 
    String insert = "INSERT INTO tbl_formerpatients(`case`, `id`, ward, department, admissionDate, dischargeDate) VALUES('" 
      + patient.getCaseId() + "', '" + patient.getId() + "', '" + patient.getWard() + "', '" 
      + patient.getDepartment() + "', '" + patient.getAdmissionDateTime().toString() + "', '" 
      + patient.getDischargeDateTime().toString() + "')"; 
    try (Connection dbConnection = connection.getDBConnection(); 
     Statement statement = dbConnection.prepareStatement(insert)) { 
     statement.executeUpdate(insert); 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
} 

public int countInpatients() { 
    int numberOfPatients = 0; 
    String query = "SELECT COUNT(id) AS numberOfPatients FROM tbl_inpatients"; 
    try (Connection dbConnection = connection.getDBConnection(); 
      Statement statement = dbConnection.createStatement();) { 
     ResultSet rs = statement.executeQuery(query); 
     while (rs.next()) { 
      numberOfPatients = rs.getInt(1); 
     } 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
    return numberOfPatients; 
} 

public int countPatients() { 
    int numberOfPatients = 0; 
    String query = "SELECT COUNT(id) AS numberOfPatients FROM tbl_patient"; 
    try (Connection dbConnection = connection.getDBConnection(); 
      Statement statement = dbConnection.createStatement();) { 
     ResultSet rs = statement.executeQuery(query); 
     while (rs.next()) { 
      numberOfPatients = rs.getInt(1); 
     } 
    } catch (SQLException e) { 
     System.out.println(e.getMessage()); 
    } 
    return numberOfPatients; 
} 

テスト

public class PatientRepositoryMySqlImplTest { 

PatientRepository testPatientRepository; 

Patient testPatient; 

Patient testPatientTwo; 

List<Patient> testBothPatients; 

DatabaseConnection testConnection; 

PatientGenerator testPatientGenerator; 

Firstnames testFirstnames; 

Lastnames testLastnames; 

Departments testDepartments; 

Wards testWards; 

@Before 
public void setUp() throws Exception { 

    testDepartments = JAXB.unmarshal(ClassLoader.getSystemResource("departments.xml"), Departments.class); 
    testWards = JAXB.unmarshal(ClassLoader.getSystemResource("wards.xml"), Wards.class); 
    testLastnames = JAXB.unmarshal(ClassLoader.getSystemResource("lastnames.xml"), Lastnames.class); 
    testFirstnames = JAXB.unmarshal(ClassLoader.getSystemResource("firstnames.xml"), Firstnames.class); 

    testPatientGenerator = new PatientGeneratorImpl(testFirstnames, testLastnames, testDepartments, testWards); 

    testPatient = testPatientGenerator.randomizeNewPatient(); 

    testPatientTwo = testPatientGenerator.randomizeNewPatient(); 

    testBothPatients = new ArrayList<Patient>(); 

    testConnection = new MySqlConnection(); 

    testPatientRepository = new PatientRepositoryMySqlImpl(testConnection, testPatientGenerator); 

    testPatientRepository.admitRandomPatient(); 

} 

@Test 
public void testAdmitRandomPatient() { 

    testPatient = testPatientRepository.admitRandomPatient(); 

    assertTrue(testPatient.isValid()); 
} 

@Test 
public void testGetRandomInpatient() { 

    testPatient = testPatientRepository.getRandomInpatient(); 

    assertTrue(testPatient.isValid()); 
} 

@Test 
public void testDischargeRandomPatientValid() { 

    testPatient = testPatientRepository.dischargeRandomPatient(); 

    assertTrue(testPatient.isValid()); 
    assertTrue(testPatient.getCaseId() != 0); 
} 

@Test 
public void testDischargeRandomPatientDatabase() { 

    int beforeDischarge = testPatientRepository.countInpatients(); 
    testPatient = testPatientRepository.dischargeRandomPatient(); 
    int afterDischarge = testPatientRepository.countInpatients(); 

    assertTrue(afterDischarge == beforeDischarge - 1); 

} 

@Test(expected = IllegalArgumentException.class) 
public void testInsertPatientWitIncompletePatient() { 

    testPatient.setFirstname(""); 

    testPatientRepository.insertPatient(testPatient); 
} 

@Test 
public void testTransferRandomPatient() { 

    testPatient = testPatientRepository.transferRandomPatient(); 

    assertTrue(testPatient.getDepartment() != testPatient.getPriorDepartment()); 
} 

@Test 
public void testInsertPatient() { 

    int numberOfPatients = testPatientRepository.countInpatients(); 

    testPatientRepository.insertPatient(testPatient); 

    assertTrue(testPatientRepository.countInpatients() >= numberOfPatients); 
} 

@Test 
public void testInsertListOfPatients() { 

    testBothPatients.add(testPatient); 
    testBothPatients.add(testPatientTwo); 

    int countInpatientsBeforeInsertion = testPatientRepository.countPatients(); 

    testPatientRepository.insertListOfPatients(testBothPatients); 

    int countInpatientsAfterInsertion = testPatientRepository.countPatients(); 
    assertTrue(countInpatientsAfterInsertion > countInpatientsBeforeInsertion); 

} 

編集:

@Test 
public void mockThrowsException() { 

    PatientRepository testPatientRepository = mock(PatientRepositoryMySqlImpl.class); 

    when(testPatientRepository.getRandomPatient()).thenThrow(SQLException.class); 

    testPatientRepository.admitRandomPatient(); 

} 
+2

例外をスローするモックを使用 – Stultuske

+0

Unittestの場合、少なくともDatabaseConnectionをモックする必要があります。データがDBに書き込まれたことを確認する代わりに、正しいステートメントが発行されたことを確認するだけで済みます。 DBConnectionのためのユニット(または統合 - )のテストは、それらが正しい結果を生成していることを確認する必要があります。 – daniu

+0

ありがとうございました!私はMockingの新人ですが、ここで多くの情報を得て、いくつかのことを試しました。私の編集を見ていただけますか、そういう意味ですか? –

答えて

2

私は完全にカバレッジを高めるために、あなたは間違いなく何かがうまくいかないシナリオとSQLException s「をシミュレートする」必要があることに同意しますが私は質問に答えますが、うまくいけば別の見通しを与える別のアプローチを紹介しましょう。

JDBCは非常に面倒であり、SQL例外をスローするテストは、おそらく書くのに最も楽しいテストではありません。加えて、私はあなたが実際に例外を処理していないことを知り、コンソールにそれらを記録するだけです。

そのため、おそらく代わりにこれで苦労しようとしているが、多分あなたは、JDBCを直接動作しますが、あなたのためのJDBCの使用の手間をラップするいくつかのライブラリを使用しないように考慮すべきです。そのようなライブラリの例として、Spring JDBC Templateを見てください。かなり古いものだとわかりますが、ちょっと、JDBCで直接作業するのもおそらく最も現代的なアプローチではないでしょうから、私は変更を少なくしようとしていますが、値。さらに、古いものではなく、空想ではないと言うかもしれません。

今はJDBC例外処理をラップしているので、特にこれらのケースをまったくカバーする必要はありません。あなたのカバレッジは自然に増加します。

もちろん、他の低レベルとそれほど低いレベルの代替(例えば、JDBI、またはJOOQなど)がありますが、これは別の話です。これらのすべてが、尋ねた。

+0

はあなたに非常に多くの@マークBramnikをありがとう、私はあなたの助けに感謝し、今私のプロジェクトでこれをしようとします。 –

+1

さて、時間がかかりましたが、最終的にはすべての変更が完了しました。私のカバレッジは非常によく増加し、私も考えて、春のJDBCテンプレートを用いて溶液がはるかにバターですが、私はそれが好き - ありがとう! –

+0

聞いてうれしい!親切な言葉のために幸運と感謝 –

関連する問題