diff --git a/code/Herzschlag/build.gradle b/code/Herzschlag/build.gradle index ac770a2..e59a085 100644 --- a/code/Herzschlag/build.gradle +++ b/code/Herzschlag/build.gradle @@ -17,6 +17,8 @@ repositories { } dependencies { + implementation 'junit:junit:4.13.1' + // Junit 5 dependencies testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.+' testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.+' diff --git a/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java b/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java index d7df62c..29bbe36 100644 --- a/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java +++ b/code/Herzschlag/src/main/java/ch/zhaw/prog2/heartbeat/Heart.java @@ -65,8 +65,23 @@ public class Heart { * InvalidValvePositionException occurs during diastole or systole * TODO Implement a pause mechanism based on the current heart rate */ - public void executeHeartBeat() throws HeartBeatDysfunctionException{ + public void executeHeartBeat() throws HeartBeatDysfunctionException, Valve.IllegalValveStateException, InvalidValvePositionException { //TODO implement + for(int i = 0; i < 2; i ++){ + if(state == State.DIASTOLE) { + executeDiastole(); + } + else if(state == State.SYSTOLE){ + executeSystole(); + } + } + + try { + Thread.currentThread().sleep((long) (1.0*heartRate/60.0*1000.0)); + System.out.println("wait:" + (1.0*heartRate/60*1000)); + } catch (InterruptedException e) { + e.printStackTrace(); + } } /** @@ -74,8 +89,35 @@ public class Heart { * * @throws Valve.IllegalValveStateException when one of the valves has an illegal State */ - public void executeDiastole() { + public void executeDiastole() throws Valve.IllegalValveStateException, InvalidValvePositionException { //TODO implement + //Segelklappen ("atrioventricular valves") öffnen + for(Half half : halves) { + if(half.isAtrioventricularValveOpen()){ + throw new InvalidValvePositionException(); + } + half.openAtrioventricularValve(); + } + + //Taschenklappen ("semilunar valves") schliessen + for(Half half : halves) { + if(!half.isSemilunarValveOpen()){ + throw new InvalidValvePositionException(); + } + half.closeSemilunarValve(); + } + + //Vorhöfe ("atria") entspannen + for(Half half : halves) { + half.relaxAtrium(); + } + + //Herzkammern ("ventricle") entspannen + for(Half half : halves) { + half.relaxVentricle(); + } + + state = State.SYSTOLE; } /** @@ -83,8 +125,36 @@ public class Heart { * * @throws Valve.IllegalValveStateException when one of the valves has an illegal State */ - public void executeSystole() { + public void executeSystole() throws Valve.IllegalValveStateException, InvalidValvePositionException { //TODO implement + + //Segelklappen schliessen + for(Half half : halves) { + if(!half.isAtrioventricularValveOpen()){ + throw new InvalidValvePositionException(); + } + half.closeAtrioventricularValve(); + } + + //Taschenklappen öffnen + for(Half half : halves) { + if(half.isSemilunarValveOpen()){ + throw new InvalidValvePositionException(); + } + half.openSemilunarValve(); + } + + //Herzkammern kontrahieren + for(Half half : halves) { + half.contractAtrium(); + } + + //Vorhöfe kontrahieren + for(Half half : halves) { + half.contractVentricle(); + } + + state = State.DIASTOLE; } public State getState() { @@ -138,8 +208,22 @@ public class Heart { * * @param args */ - public static void main(String[] args) throws HeartBeatDysfunctionException { + public static void main(String[] args) throws HeartBeatDysfunctionException, Valve.IllegalValveStateException, InvalidValvePositionException { Heart heart = new Heart(); heart.executeHeartBeat(); } + + public static class InvalidValvePositionException extends Exception { + + public InvalidValvePositionException() { + } + + public InvalidValvePositionException(String message) { + super(message); + } + + public InvalidValvePositionException(String message, Throwable cause) { + super(message, cause); + } + } } diff --git a/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java b/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java index d3b7968..5f9cd4d 100644 --- a/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java +++ b/code/Herzschlag/src/test/java/ch/zhaw/prog2/heartbeat/HeartTest.java @@ -7,11 +7,22 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; import ch.zhaw.prog2.heartbeat.parts.Valve; +import org.junit.Before; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import ch.zhaw.prog2.heartbeat.Heart.State; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnitRunner; +@RunWith(MockitoJUnitRunner.class) class HeartTest { /** * This is a very simple test to check if Junit and Mockito are properly set up. @@ -26,7 +37,7 @@ class HeartTest { * Tests a single heartbeat */ @Test - void testHeartBeat() throws Heart.HeartBeatDysfunctionException { + void testHeartBeat() throws Heart.HeartBeatDysfunctionException, Valve.IllegalValveStateException, Heart.InvalidValvePositionException { Heart heart = new Heart(); State startState = heart.getState(); @@ -40,7 +51,7 @@ class HeartTest { * Tests if the valves are open or closed depending on the status of the heart */ @Test - void testValveStatus() throws Heart.HeartBeatDysfunctionException { + void testValveStatus() throws Heart.HeartBeatDysfunctionException, Valve.IllegalValveStateException, Heart.InvalidValvePositionException { Heart heart = new Heart(); heart.executeHeartBeat(); @@ -78,9 +89,15 @@ class HeartTest { * with exception Stubbing */ @Test - void testExecuteHartBeatErrorBehaviourWithStubbing() throws Valve.IllegalValveStateException { + void testExecuteHartBeatErrorBehaviourWithStubbing() { //TODO implement - fail(); + Half half = mock(Half.class, withSettings().useConstructor(Half.Side.LEFT)); + Heart heart = new Heart(half, new Half(Half.Side.RIGHT)); + half.initializeState(heart.getState()); + when(half.isAtrioventricularValveOpen()).thenReturn(false); + + assertThrows(Heart.HeartBeatDysfunctionException .class, // verification using lambda + () -> heart.executeHeartBeat()); } /** @@ -92,9 +109,60 @@ class HeartTest { * */ @Test - void testValvesBehavior() { + void testValvesBehavior() throws Valve.IllegalValveStateException, Heart.HeartBeatDysfunctionException, Heart.InvalidValvePositionException { //TODO implement - fail(); + Half half1 = mock(Half.class, withSettings().useConstructor(Half.Side.LEFT)); + Half half2 = mock(Half.class, withSettings().useConstructor(Half.Side.RIGHT)); + Heart heart = new Heart(half1, half2); + + heart.executeHeartBeat(); + + InOrder inOrderHalf1 = inOrder(half1); + + inOrderHalf1.verify(half1).closeAtrioventricularValve(); + inOrderHalf1.verify(half1).openSemilunarValve(); + inOrderHalf1.verify(half1).relaxAtrium(); + inOrderHalf1.verify(half1).relaxVentricle(); + + inOrderHalf1.verify(half1).closeAtrioventricularValve(); + inOrderHalf1.verify(half1).openSemilunarValve(); + inOrderHalf1.verify(half1).contractAtrium(); + inOrderHalf1.verify(half1).contractVentricle(); + + inOrderHalf1.verifyNoMoreInteractions(); + + InOrder inOrderHalf2 = inOrder(half2); + + inOrderHalf2.verify(half2).closeAtrioventricularValve(); + inOrderHalf2.verify(half2).openSemilunarValve(); + inOrderHalf2.verify(half2).relaxAtrium(); + inOrderHalf2.verify(half2).relaxVentricle(); + + inOrderHalf2.verify(half2).closeAtrioventricularValve(); + inOrderHalf2.verify(half2).openSemilunarValve(); + inOrderHalf2.verify(half2).contractAtrium(); + inOrderHalf2.verify(half2).contractVentricle(); + + inOrderHalf2.verifyNoMoreInteractions(); + + } + + /** + * This is code used for the lecture slide. + */ + @Test + void testForSlide() throws Valve.IllegalValveStateException, Heart.InvalidValvePositionException { + Half mockedHalf = mock(Half.class); + Heart heart = new Heart(mockedHalf, new Half(Half.Side.RIGHT)); + heart.setState(State.SYSTOLE); + heart.initalizeState(); + + when(mockedHalf.isAtrioventricularValveOpen()).thenReturn(false); + when(mockedHalf.isSemilunarValveOpen()).thenReturn(true); + heart.executeSystole(); + + verify(mockedHalf).contractVentricle(); + verify(mockedHalf, times(1)).contractAtrium(); } }