diff --git a/v2/cassette/cassette.go b/v2/cassette/cassette.go index 9ef4989..2190704 100644 --- a/v2/cassette/cassette.go +++ b/v2/cassette/cassette.go @@ -46,7 +46,11 @@ const ( var ( // ErrInteractionNotFound indicates that a requested // interaction was not found in the cassette file - ErrInteractionNotFound = errors.New("Requested interaction not found") + ErrInteractionNotFound = errors.New("requested interaction not found") + + // ErrCassetteNotFound indicates that a requested + // casette doesn't exist (only in Replaying mode) + ErrCassetteNotFound = errors.New("requested cassette not found") ) // Request represents a client request as recorded in the diff --git a/v2/recorder/recorder.go b/v2/recorder/recorder.go index 50d09eb..5d74b9d 100644 --- a/v2/recorder/recorder.go +++ b/v2/recorder/recorder.go @@ -174,33 +174,41 @@ func New(cassetteName string) (*Recorder, error) { // NewAsMode creates a new recorder in the specified mode func NewAsMode(cassetteName string, mode Mode, realTransport http.RoundTripper) (*Recorder, error) { - var c *cassette.Cassette + var r = &Recorder{ + mode: mode, + realTransport: realTransport, + } + + if r.realTransport == nil { + r.realTransport = http.DefaultTransport + } + + // Disabled mode has no cassette + if mode == ModeDisabled { + return r, nil + } + cassetteFile := fmt.Sprintf("%s.yaml", cassetteName) - if mode != ModeDisabled { - // Depending on whether the cassette file exists or not we - // either create a new empty cassette or load from file - if _, err := os.Stat(cassetteFile); os.IsNotExist(err) || mode == ModeRecording { - // Create new cassette and enter in recording mode - c = cassette.New(cassetteName) - mode = ModeRecording - } else { - // Load cassette from file and enter replay mode or replay/record mode - c, err = cassette.Load(cassetteName) - if err != nil { - return nil, err - } + // Check if the cassette exists + if _, err := os.Stat(cassetteFile); os.IsNotExist(err) { + // Replaying mode should fail if no cassette exists + if mode == ModeReplaying { + return nil, cassette.ErrCassetteNotFound } - } - if realTransport == nil { - realTransport = http.DefaultTransport + // Otherwise we are in a recording mode, create new cassette and enter in recording mode + r.cassette = cassette.New(cassetteName) + r.mode = ModeRecording + + return r, nil } - r := &Recorder{ - mode: mode, - cassette: c, - realTransport: realTransport, + // Load cassette from file and enter replay mode or replay/record mode + var err error + r.cassette, err = cassette.Load(cassetteName) + if err != nil { + return nil, err } return r, nil diff --git a/v2/recorder/recorder_test.go b/v2/recorder/recorder_test.go index 5991e4a..9bdcbfd 100644 --- a/v2/recorder/recorder_test.go +++ b/v2/recorder/recorder_test.go @@ -127,10 +127,19 @@ func TestRecord(t *testing.T) { } } +func TestReplayingModeFailsWithEmptyCassette(t *testing.T) { + _, cassPath, _ := setupTests(t, "replaying_test") + + _, err := recorder.NewAsMode(cassPath, recorder.ModeReplaying, nil) + if err != cassette.ErrCassetteNotFound { + t.Fatalf("expected cassette.ErrCassetteNotFound, got %v", err) + } +} + func TestModeContextTimeout(t *testing.T) { // Record initial requests runID, cassPath, tests := setupTests(t, "record_playback_timeout") - _, serverURL := httpRecorderTest(t, runID, tests, cassPath, recorder.ModeReplaying) + _, serverURL := httpRecorderTest(t, runID, tests, cassPath, recorder.ModeReplayingOrRecording) // Re-run without the actual server r, err := recorder.New(cassPath) @@ -152,7 +161,7 @@ func TestModeContextTimeout(t *testing.T) { func TestModePlaybackMissing(t *testing.T) { // Record initial requests runID, cassPath, tests := setupTests(t, "record_playback_missing_test") - httpRecorderTest(t, runID, tests, cassPath, recorder.ModeReplaying) + httpRecorderTest(t, runID, tests, cassPath, recorder.ModeReplayingOrRecording) // setup same path but a new runID so requests won't match runID = time.Now().Format(time.RFC3339Nano)