我正在嘗試在我的InsertCashTransaction類中對方法Execute()進行單元測試。我想測試它是否正確地爲User.Balance分配一個新值。你可以在這裏看到兩班如何對一個方法正確地分配一個新值給另一個類進行單元測試
InsertCashTransaction類
public class InsertCashTransaction : Transaction
{
private IUser _userI;
public InsertCashTransaction(User user, DateTime date, decimal amount) : base(user, date, amount)
{
User = user;
}
public InsertCashTransaction(IUser UserI)
{
this._userI = UserI;
}
public override string ToString()
{
return $"Transaction number: {TransactionId}, Date: {Date}: {Amount} has been inserted onto {User.Username}'s wallet.";
}
// Method I am trying to test
public override void Execute()
{
if (Amount > 0)
{
User.Balance = User.Balance + Amount;
}
else if (Amount <= 0)
{
throw new ArgumentException("Not allowed to withdraw from users balance nor insert 0");
}
}
}
User類
public class User : IUser
{
private int _userid;
private string _firstname;
private string _lastname;
private string _username;
private string _email;
private decimal _balance;
public int UserID
{
get { return _userid; }
set
{
if (value < 1)
{
throw new ArgumentException("ID cannot be below one");
}
_userid = value;
}
}
public string FirstName
{
get { return _firstname; }
set
{
CheckIfNull(value);
ValidateName(value);
_firstname = value;
}
}
public string LastName
{
get { return _lastname; }
set
{
CheckIfNull(value);
ValidateName(value);
_lastname = value;
}
}
public string Username
{
get { return _username; }
set
{
CheckIfNull(value);
foreach (char item in value)
{
if (char.IsUpper(item))
{
throw new ArgumentException("Username is not allowed to hold use upper case letter");
}
if (char.IsSymbol(item))
{
throw new ArgumentException("Username must not contains symbols");
} else if (item == '-')
{
throw new ArgumentException("Username must not contain symbols");
}
}
_username = value;
}
}
public string Email
{
get { return _email; }
set
{
CheckIfNull(value);
//Creates two out of the email separated by @
string[] separation = value.Split('@');
string localPart = separation[0];
string domain = separation[1];
foreach (char item in localPart)
{
if (char.IsLetterOrDigit(item) == false)
{
if (item != '.' || item != '-' || item != '_' || item != ',')
{
continue;
}
else
{
throw new ArgumentException("Not a valid email");
}
}
}
// Check if domain starts with '.' or '-'
if (domain.Contains("."))
{
if (domain.StartsWith(".") || domain.StartsWith("-") || domain.EndsWith(".") || domain.EndsWith("-"))
{
throw new ArgumentException("domain must not start with .");
}
}
foreach (char item in domain)
{
if (char.IsSymbol(item))
{
throw new ArgumentException("Domain must not contain any symbols");
}
}
_email = value;
}
}
public decimal Balance
{
get { return _balance; }
set
{
if (value < 0)
{
throw new ArgumentException("Balance is below 0");
}
_balance = value;
}
}
public override string ToString()
{
return $"{FirstName}, {LastName}, {Email}";
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (this.GetType() != obj.GetType())
{
return false;
}
return Equals((User)obj);
}
public bool Equals(User obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
if (this.GetHashCode() != obj.GetHashCode())
{
return false;
}
System.Diagnostics.Debug.Assert(base.GetType() != typeof(object));
if (!base.Equals(obj))
{
return false;
}
return UserID.Equals(obj.UserID);
}
public override int GetHashCode()
{
return UserID.GetHashCode();
}
public int CompareTo(User user)
{
if (UserID > user.UserID)
{
return -1;
}
return 1;
}
public User(int id, string firstName, string lastName, string username, string email, decimal balance)
{
UserID = id;
FirstName = firstName;
LastName = lastName;
Username = username;
Email = email;
Balance = balance;
}
public User()
{
}
public string CheckIfNull(string element)
{
if (string.IsNullOrEmpty(element))
{
throw new ArgumentNullException("Something is missing");
}
return element;
}
protected string ValidateName(string name)
{
foreach (char item in name)
{
if (char.IsDigit(item))
{
throw new ArgumentException("Something is wrong in either firstname or lastname");
}
}
return name;
}
}
我到目前爲止已經試過創建用戶的界面並通過Nsubsitute試圖在考試中替代你的班級看到這裏
IUSER接口
public interface IUser
{
int UserID { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
string Username { get; set; }
string Email { get; set; }
decimal Balance { get; set; }
}
InsertCashTransactionTest類
[TestFixture]
class InsertCashTransactionTest
{
[TestCase(0)]
[TestCase(-1)]
[TestCase(-10)]
[TestCase(-50)]
public void AmountBelowZero_throwException(decimal number)
{
IUser user = Substitute.For<IUser>();
InsertCashTransaction icTransaction = new InsertCashTransaction(user);
icTransaction.Amount = number;
Assert.Catch<ArgumentException>(() => icTransaction.Execute());
}
// Test that isn't working
[TestCase(1)]
[TestCase(10)]
[TestCase(50)]
public void AmountAboveZero_InsertToUserBalance(decimal number)
{
//Arrange
IUser user = Substitute.For<IUser>();
InsertCashTransaction icTransaction = new InsertCashTransaction(user);
user.Balance = 0;
icTransaction.Amount = number;
decimal actualresult = number;
// Act
// Somewhere here it goes wrong
icTransaction.Execute();
//Assert
Assert.AreEqual(actualresult, user.Balance);
}
我的實際問題 當我嘗試運行測試,我得到一個Nullreference例外,我的問題是我不知道我在做什麼錯了。問題似乎是每當icTransaction.Execute()被調用時。我希望你能幫我弄清楚我做錯了什麼。
請問是否有什麼不清楚,需要進一步解釋
您初始化'公共InsertCashTransaction(IUSER UserI) { this._userI = UserI; }'但在'Execute'方法中,您可以檢索User.Balance + Amount值。你確定你發佈了所有'InsertCashTransaction'類的代碼,或者它是錯誤的嗎? –
我已經發布了來自InsertCashTransaction類的所有代碼 – Lumbaz
看起來你的第二個構造函數沒有正確初始化基類,所以'User'是'null'。嘗試移除該構造函數,而是讓第一個構造函數使用'IUser'而不是'User'(您還需要對基類構造函數進行相同的更改)。然後在單元測試中使用三參數構造函數。 – lesscode