Version 3.0.381

This commit is contained in:
Anja 2024-04-09 12:53:23 +02:00
parent f963c0a219
commit 3a363acf3a
1525 changed files with 60589 additions and 125098 deletions

View file

@ -0,0 +1,108 @@
using System;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
using ShareeBike.Model.Connector;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.AuthCommand;
using ShareeBike.Repository.Exception;
namespace SharedBusinessLogic.Tests.Model.Bikes.BikeInfoNS.BikeNS.Command
{
[TestFixture]
public class TestAuthCommand
{
/// <summary>
/// Use case: Authenticate.
/// Final state: Authentication successfully
/// </summary>
[Test]
public async Task TestAuth()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IAuthCommandListener>();
await InvokeAsync<TestAuthCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
await connector.Command.CalculateAuthKeys(Arg.Any<IBikeInfoMutable>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.Authenticate);
await connector.Command.CalculateAuthKeys(bike);
});
}
/// <summary>
/// Use case: Authenticate.
/// Final state: Authentication failed
/// </summary>
[Test]
public void TestAuthNoWebException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IAuthCommandListener>();
bike.LockInfo.State.Returns(LockingState.Closed);
connector.Command.CalculateAuthKeys(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new WebConnectFailureException("Context info.", new System.Exception("hoppla")));
Assert.That(
async () => await InvokeAsync<TestAuthCommand>(
bike,
() => false, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<WebConnectFailureException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.Authenticate);
await connector.Command.CalculateAuthKeys(bike);
await listener.ReportStateAsync(State.WebConnectFailed, "Context info.");
});
}
/// <summary>
/// Use case: Authenticate.
/// Final state: Authentication failed
/// </summary>
[Test]
public void TestAuthGeneralException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IAuthCommandListener>();
bike.LockInfo.State.Returns(LockingState.Closed);
connector.Command.CalculateAuthKeys(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new Exception("Context info."));
Assert.That(
async () => await InvokeAsync<TestAuthCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.Authenticate);
await connector.Command.CalculateAuthKeys(bike);
await listener.ReportStateAsync(State.GeneralAuthError, "Context info.");
});
}
}
}

View file

@ -0,0 +1,139 @@
using System;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
using ShareeBike.Model.Connector;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.CancelReservationCommand;
using ShareeBike.Repository.Exception;
namespace SharedBusinessLogic.Tests.Model.Bikes.BikeInfoNS.BikeNS.Command
{
[TestFixture]
public class TestCancelReservationCommand
{
/// <summary>
/// Use case: Cancel reservation.
/// Final state: Reservation canceled successfully
/// </summary>
[Test]
public async Task TestCancelReservation()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<ICancelReservationCommandListener>();
await InvokeAsync<TestCancelReservationCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
await connector.Command.DoCancelReservation(Arg.Any<IBikeInfoMutable>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.CancelReservation);
await connector.Command.DoCancelReservation(bike);
});
}
/// <summary>
/// Use case: Cancel reservation.
/// Final state: Still reserved.
/// </summary>
[Test]
public void TestCancelReservationNoWebException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<ICancelReservationCommandListener>();
bike.LockInfo.State.Returns(LockingState.Closed);
connector.Command.DoCancelReservation(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new WebConnectFailureException("Context info.", new System.Exception("hoppla")));
Assert.That(
async () => await InvokeAsync<TestCancelReservationCommand>(
bike,
() => false, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<WebConnectFailureException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.CancelReservation);
await connector.Command.DoCancelReservation(bike);
await listener.ReportStateAsync(State.WebConnectFailed, "Context info.");
});
}
/// <summary>
/// Use case: Cancel reservation.
/// Final state: Still reserved.
/// </summary>
[Test]
public void TestCancelReservationGeneralException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<ICancelReservationCommandListener>();
connector.Command.DoCancelReservation(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new Exception("Context info."));
Assert.That(
async () => await InvokeAsync<TestCancelReservationCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.CancelReservation);
await connector.Command.DoCancelReservation(bike);
await listener.ReportStateAsync(State.GeneralCancelReservationError, "Context info.");
});
}
/// <summary>
/// Use case: Cancel reservation.
/// Final state: Still reserved.
/// </summary>
[Test]
public void TestCancelReservationTooManyBikesException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<ICancelReservationCommandListener>();
bike.Id.Returns("1543");
connector.Command.DoCancelReservation(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new InvalidAuthorizationResponseException("mail", new ShareeBike.Repository.Response.ResponseBase()));
Assert.That(
async () => await InvokeAsync<TestCancelReservationCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<InvalidAuthorizationResponseException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.CancelReservation);
await connector.Command.DoCancelReservation(bike);
await listener.ReportStateAsync(State.InvalidResponse, "Your session has expired. Please login new and try again.");
});
}
}
}

View file

@ -0,0 +1,469 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
using ShareeBike.Services.BluetoothLock;
using ShareeBike.Services.Geolocation;
using ShareeBike.Repository.Request;
using ShareeBike.Model.Connector;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.EndRentalCommand;
using ShareeBike.Model;
using ShareeBike.Repository.Exception;
using ShareeBike.Model.State;
namespace SharedBusinessLogic.Tests.Model.Bikes.BikeInfoNS.BikeNS.Command
{
[TestFixture]
public class TestEndRentalCommand
{
/// <summary>
/// Use case: End rental.
/// Final state: Rental ended successfully
/// </summary>
[Test]
[Ignore("bike.State.Value should be FeedbackPending")]
public async Task TestReturnClosingLockLocationAvailable()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
var closingLockLocation = Substitute.For<IGeolocation>();
closingLockLocation.Latitude.Returns(7);
closingLockLocation.Longitude.Returns(9);
closingLockLocation.Timestamp.Returns(DateTimeOffset.MinValue);
bike.LockInfo.Location.Returns((IGeolocation)closingLockLocation); // When locking bike geolocation was available.
var endRentalLocation = closingLockLocation;
var bookingFinished = connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 7 && x.Longitude == 9));
await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
listener.ReportStep(Step.ReturnBike);
var bookingFinished = await connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 7 && x.Longitude == 9));
});
Assert.That(bookingFinished, Is.Not.Null);
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.FeedbackPending));
}
// <summary>
// Use case: End rental.
// Final state: Rental ended successfully
// </summary>
[Test]
[Ignore("bike.State.Value should be FeedbackPending")]
public async Task TestReturnLastGeolocationNullLockInReach()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.Location.Returns((IGeolocation)null); // Simulate that when locking bike geolocation was not available
var newLockLocation = Substitute.For<IGeolocation>(); // Get geolocation from end rental
newLockLocation.Latitude.Returns(7);
newLockLocation.Longitude.Returns(9);
newLockLocation.Timestamp.Returns(DateTimeOffset.MinValue);
var endRentalLocation = geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromResult(newLockLocation));
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
var bookingFinished = connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 7 && x.Longitude == 9));
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
var endRentalLocation = await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.ReportStep(Step.ReturnBike);
var bookingFinished = await connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 7 && x.Longitude == 9));
});
Assert.That(bookingFinished, Is.Not.Null);
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.FeedbackPending));
}
/// <summary>
/// Use case: End rental.
/// Final state: Still rented.
/// </summary>
[Test]
public async Task TestReturnLastGeolocatonNullLockOutOfReachNoGPSDataDoNotReturn()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Disconnected); // Simulate bike not in reach.
await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
var task = connector.Command.DidNotReceive().DoReturn(Arg.Any<IBikeInfoMutable>(), Arg.Any<LocationDto>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
await listener.ReportStateAsync(State.NoGPSData, "There is no geolocation information available since lock is not connected");
});
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.Booked));
}
/// <summary>
/// Use case: End rental.
/// Final state: Still rented.
/// </summary>
[Test]
public void TestReturnLastGeolocatonNullLockInReachGetGeolocationException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns<Task<IGeolocation>>(x => throw new Exception("Ups...")); // Simulate error query for geolocation.
Assert.That(
async () => await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<Exception>());
connector.Command.DidNotReceive().DoReturn(Arg.Any<IBikeInfoMutable>(), Arg.Any<LocationDto>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
var endRentalLocation = await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
await listener.ReportStateAsync(State.GeneralQueryLocationFailed, "Ups...");
});
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.Booked));
}
/// <summary>
/// Use case: End rental.
/// Final state: Still rented.
/// </summary>
[Test]
[Ignore("bookingFinished should be null")]
public void TestReturnLastGeolocatonNullReturnException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
var newLockLocation = Substitute.For<IGeolocation>(); // Get geolocation from end rental
newLockLocation.Latitude.Returns(7);
newLockLocation.Longitude.Returns(9);
newLockLocation.Timestamp.Returns(DateTimeOffset.MinValue);
var endRentalLocation = geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromResult(newLockLocation));
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromResult(newLockLocation));
var bookingFinished = connector.Command.DoReturn(Arg.Any<IBikeInfoMutable>(), Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x =>
throw new Exception("Ups..."));
Assert.That(
async () => await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
var endRentalLocation = await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.ReportStep(Step.ReturnBike);
var bookingFinished = await connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 7 && x.Longitude == 9));
await listener.ReportStateAsync(State.GeneralEndRentalError, "Ups...");
});
Assert.That(bookingFinished, Is.Null);
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.Booked));
}
/// <summary>
/// Use case: End rental.
/// Final state: Still rented.
/// </summary>
[Test]
[Ignore("bookingFinished should be null")]
public void TestReturnReturnNoWebException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
var newLockLocation = Substitute.For<IGeolocation>(); // Get geolocation from end rental
newLockLocation.Latitude.Returns(7);
newLockLocation.Longitude.Returns(9);
newLockLocation.Timestamp.Returns(DateTimeOffset.MinValue);
var endRentalLocation = geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromResult(newLockLocation));
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromResult(newLockLocation));
var bookingFinished = connector.Command.DoReturn(Arg.Any<IBikeInfoMutable>(), Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x
=> throw new WebConnectFailureException("Context info.", new System.Exception("hoppla")));
Assert.That(
async () => await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => false, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<WebConnectFailureException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
var endRentalLocation = await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.ReportStep(Step.ReturnBike);
var bookingFinished = await connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 7 && x.Longitude == 9));
await listener.ReportStateAsync(State.WebConnectFailed, "Context info.");
});
Assert.That(bookingFinished, Is.Null);
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.Booked));
}
/// <summary>
/// Use case: End rental.
/// Final state: Still rented.
/// </summary>
[Test]
[Ignore("Exception needs to be initialized correctly. bookingFinished should be null")]
public void TestReturnNotAtStationException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.Id.Returns("1545");
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
var newLockLocation = Substitute.For<IGeolocation>(); // Get geolocation from end rental
newLockLocation.Latitude.Returns(7);
newLockLocation.Longitude.Returns(9);
newLockLocation.Timestamp.Returns(DateTimeOffset.MinValue);
var endRentalLocation = geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromResult(newLockLocation));
geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns(Task.FromResult(newLockLocation));
NotAtStationException.IsNotAtStation("Failure 2178: bike 1545 out of GEO fencing. 15986 meter distance to next station 42. OK: bike 1545 locked confirmed", out NotAtStationException notAtStationException);
notAtStationException.Distance.Returns(15986);
notAtStationException.StationNr.Returns("42");
var bookingFinished = connector.Command.DoReturn(Arg.Any<IBikeInfoMutable>(), Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x
=> throw notAtStationException);
Assert.That(
async () => await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<NotAtStationException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
var endRentalLocation = await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.ReportStep(Step.ReturnBike);
var bookingFinished = await connector.Command.DoReturn(bike, Arg.Is<LocationDto>(x => x.Latitude == 7 && x.Longitude == 9));
await listener.ReportStateAsync(State.NotAtStation, "End rental outside or at unsuitable station is not possible. Distance to next suitable station 42 is 15986 m.\r\n\r\nNote: Your GPS data may not be up to date. So if you are at a suitable station, please simply try again so that your location is queried again.");
});
Assert.That(bookingFinished, Is.Null);
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.Booked));
}
/// <summary>
/// Use case: End rental.
/// Final state: Still rented.
/// </summary>
[Test]
[Ignore("Exception needs to be initialized correctly. bookingFinished should be null")]
public void TestReturnNoGPSDataException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var geolocation = Substitute.For<IGeolocationService>();
var locks = Substitute.For<ILocksService>();
static DateTime dateTime() => DateTime.MinValue;
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IEndRentalCommandListener>();
bike.State.Value.Returns(InUseStateEnum.Booked);
bike.LockInfo.Location.Returns((IGeolocation)null); // When locking bike geolocation was not available.
locks[0].GetDeviceState().Returns(DeviceState.Connected); // Simulate bike in reach.
var endRentalLocation = geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>())
.Returns((IGeolocation)null);
NoGPSDataException.IsNoGPSData("Failure 2245: No GPS data, state change forbidden.", out NoGPSDataException noGPSDataException);
var bookingFinished = connector.Command.DoReturn(Arg.Any<IBikeInfoMutable>(), Arg.Any<LocationDto>()).Returns<BookingFinishedModel>(x =>
throw noGPSDataException);
locks.DidNotReceive().DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
Assert.That(
async () => await InvokeAsync<TestEndRentalCommand>(
bike,
geolocation,
locks,
dateTime,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<NoGPSDataException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.GetLocation);
var location = bike.LockInfo.Location;
locks[0].GetDeviceState();
var endRentalLocation = await geolocation.GetAsync(Arg.Any<CancellationToken?>(), Arg.Any<DateTime?>());
listener.ReportStep(Step.ReturnBike);
var bookingFinished = await connector.Command.DoReturn(bike, null);
await listener.ReportStateAsync(State.NoGPSData, "Failure 2245: No GPS data, state change forbidden.");
});
Assert.That(bookingFinished, Is.Null);
Assert.That(bike.State.Value, Is.EqualTo(InUseStateEnum.Booked));
}
}
}

View file

@ -0,0 +1,205 @@
using System;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
using ShareeBike.Model.Connector;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.StartRentalCommand;
using ShareeBike.Repository.Exception;
namespace SharedBusinessLogic.Tests.Model.Bikes.BikeInfoNS.BikeNS.Command
{
[TestFixture]
public class TestStartRentalCommand
{
/// <summary>
/// Use case: Start rental.
/// Final state: Rental started successfully
/// </summary>
[Test]
public async Task TestLockClosedStartRental()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartRentalCommandListener>();
bike.LockInfo.State.Returns(LockingState.Closed);
await InvokeAsync<TestStartRentalCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
await connector.Command.DoBookAsync(Arg.Any<IBikeInfoMutable>(), LockingAction.Open);
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.RentBike);
await connector.Command.DoBookAsync(bike, LockingAction.Open);
});
}
/// <summary>
/// Use case: Start rental.
/// Final state: Still reserved.
/// </summary>
[Test]
public void TestLockClosedStartRentalNoWebException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartRentalCommandListener>();
bike.LockInfo.State.Returns(LockingState.Closed);
connector.Command.DoBookAsync(Arg.Any<IBikeInfoMutable>(), LockingAction.Open).Returns(x
=> throw new WebConnectFailureException("Context info.", new System.Exception("hoppla")));
Assert.That(
async () => await InvokeAsync<TestStartRentalCommand>(
bike,
() => false, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<WebConnectFailureException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.RentBike);
await connector.Command.DoBookAsync(bike, LockingAction.Open);
await listener.ReportStateAsync(State.WebConnectFailed, "Context info.");
});
}
/// <summary>
/// Use case: Start rental.
/// Final state: Still reserved.
/// </summary>
[Test]
public void TestLockClosedStartRentalGeneralException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartRentalCommandListener>();
bike.LockInfo.State.Returns(LockingState.Closed);
connector.Command.DoBookAsync(Arg.Any<IBikeInfoMutable>(), LockingAction.Open).Returns(x
=> throw new Exception("Context info."));
Assert.That(
async () => await InvokeAsync<TestStartRentalCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.RentBike);
await connector.Command.DoBookAsync(bike, LockingAction.Open);
await listener.ReportStateAsync(State.GeneralStartRentalError, "Context info.");
});
}
/// <summary>
/// Use case: Start rental.
/// Final state: Rental started successfully
/// </summary>
[Test]
public async Task TestLockOpenStartRental()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartRentalCommandListener>();
bike.LockInfo.State.Returns(LockingState.Open);
await InvokeAsync<TestStartRentalCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
await connector.Command.DoBookAsync(Arg.Any<IBikeInfoMutable>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.RentBike);
await connector.Command.DoBookAsync(bike);
});
}
/// <summary>
/// Use case: Start rental.
/// Final state: Still reserved.
/// </summary>
[Test]
public void TestLockOpenStartRentalNoWebException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartRentalCommandListener>();
bike.LockInfo.State.Returns(LockingState.Open);
connector.Command.DoBookAsync(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new WebConnectFailureException("Context info.", new System.Exception("hoppla")));
Assert.That(
async () => await InvokeAsync<TestStartRentalCommand>(
bike,
() => false, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<WebConnectFailureException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.RentBike);
await connector.Command.DoBookAsync(bike);
await listener.ReportStateAsync(State.WebConnectFailed, "Context info.");
});
}
/// <summary>
/// Use case: Start rental.
/// Final state: Still reserved.
/// </summary>
[Test]
public void TestLockOpenStartRentalGeneralException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartRentalCommandListener>();
bike.LockInfo.State.Returns(LockingState.Open);
connector.Command.DoBookAsync(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new Exception("Context info."));
Assert.That(
async () => await InvokeAsync<TestStartRentalCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.RentBike);
await connector.Command.DoBookAsync(bike);
await listener.ReportStateAsync(State.GeneralStartRentalError, "Context info.");
});
}
}
}

View file

@ -0,0 +1,148 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using NSubstitute;
using NUnit.Framework;
using ShareeBike.Model.Bikes.BikeInfoNS.BluetoothLock;
using ShareeBike.Services.BluetoothLock;
using ShareeBike.Services.Geolocation;
using ShareeBike.Repository.Request;
using ShareeBike.Model.Connector;
using static ShareeBike.Model.Bikes.BikeInfoNS.BikeNS.Command.StartReservationCommand;
using ShareeBike.Model;
using ShareeBike.Repository.Exception;
namespace SharedBusinessLogic.Tests.Model.Bikes.BikeInfoNS.BikeNS.Command
{
[TestFixture]
public class TestStartReservationCommand
{
/// <summary>
/// Use case: Start reservation.
/// Final state: Reservation started successfully
/// </summary>
[Test]
public async Task TestStartReservation()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartReservationCommandListener>();
await InvokeAsync<TestStartReservationCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener);
await connector.Command.DoReserve(Arg.Any<IBikeInfoMutable>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.ReserveBike);
await connector.Command.DoReserve(bike);
});
}
/// <summary>
/// Use case: Start reservation.
/// Final state: Reservation failed.
/// </summary>
[Test]
public void TestStartReservationNoWebException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartReservationCommandListener>();
bike.LockInfo.State.Returns(LockingState.Closed);
connector.Command.DoReserve(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new WebConnectFailureException("Context info.", new System.Exception("hoppla")));
Assert.That(
async () => await InvokeAsync<TestStartReservationCommand>(
bike,
() => false, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<WebConnectFailureException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.ReserveBike);
await connector.Command.DoReserve(bike);
await listener.ReportStateAsync(State.WebConnectFailed, "Context info.");
});
}
/// <summary>
/// Use case: Start reservation.
/// Final state: Reservation failed.
/// </summary>
[Test]
public void TestStartReservationGeneralException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartReservationCommandListener>();
connector.Command.DoReserve(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw new Exception("Context info."));
Assert.That(
async () => await InvokeAsync<TestStartReservationCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<Exception>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.ReserveBike);
await connector.Command.DoReserve(bike);
await listener.ReportStateAsync(State.GeneralStartReservationError, "Context info.");
});
}
/// <summary>
/// Use case: Start reservation.
/// Final state: Reservation failed.
/// </summary>
[Test]
[Ignore("Exception needs to be initialized correctly.")]
public void TestStartReservationTooManyBikesException()
{
var bike = Substitute.For<IBikeInfoMutable>();
var connector = Substitute.For<IConnector>();
var listener = Substitute.For<IStartReservationCommandListener>();
bike.Id.Returns("1543");
BookingDeclinedException.IsBookingDeclined("Too many bikes", out BookingDeclinedException bookingDeclinedException);
bookingDeclinedException.MaxBikesCount.Returns(3);
connector.Command.DoReserve(Arg.Any<IBikeInfoMutable>()).Returns(x
=> throw bookingDeclinedException);
Assert.That(
async () => await InvokeAsync<TestStartReservationCommand>(
bike,
() => true, // isConnectedDelegate
(isConnected) => connector,
listener),
Throws.InstanceOf<BookingDeclinedException>());
// Verify behavior
Received.InOrder(async () =>
{
listener.ReportStep(Step.ReserveBike);
await connector.Command.DoReserve(bike);
await listener.ReportStateAsync(State.TooManyBikesError, "Too many bikes");
});
}
}
}