熱鍵
- Alt+Enter: Quick+Action
- Ctrl+R,M 抽方法出來
- code snippets / live template
- constructor: ctor
- property:prop
- console.writeLine)():cw
- ctrl+R,F: Extract Field
- Alt+Insert
- 循環剪貼簿:ctrl+shift+V
測試替身有下面三種
- stub:不做驗證,單純只做模擬相依物件的行為
- mock:一開始就要把所有的都定義清楚,應該要呼叫那個方法,所有的值一定要一模一樣,否則就會報錯(嚴格,敏感,不穩定)
- spy: 則是把所有的互動先做完,只驗要驗的,剩的沒有測就是都算過,差異是一個從嚴一個從寬。(寬鬆)
因此mock和spy本身含有驗證(Assertion),而stub本身只有在模擬相依的物件而已。
比較物件屬性的方式
比較兩邊的物件包含子物件完全相同
expected.ToExpectedObject().ShouldEqual(actual);
比較以expected為主的屬性去比較相對應的actual是否相同
expected.ToExpectedObject().ShouldMatch(actual);
測試範例如下
namespace AssertionSample
{
[TestFixture]
public class AssertionSample
{
private CustomerRepo customerRepo = new CustomerRepo();
//比較物件屬性的方式
[Test]
public void CompareCustomer()
{
var actual = customerRepo.Get();
var expected = new Customer
{
Id = 2,
Age = 18,
Birthday = new DateTime(1990, 1, 26)
};
//CollectionAssert也是在比較物件的位置,所以也會有相同的問題
expected.ToExpectedObject().ShouldEqual(actual);
}
//比較集合的方式
[Test]
public void CompareCustomerList()
{
var actual = customerRepo.GetAll();
var expected = new List
{
new Customer()
{
Id = 3,
Age = 20,
Birthday = new DateTime(1993,1,2)
},
new Customer()
{
Id = 4,
Age = 21,
Birthday = new DateTime(1993,1,3)
}
};
expected.ToExpectedObject().ShouldEqual(actual);
}
//組合式物件的比較
[Test]
public void CompareComposedCustomer()
{
var actual = customerRepo.GetComposedCustomer();
var expected = new Customer()
{
Age = 30,
Id = 11,
Birthday = new DateTime(1999, 9, 9),
Order = new Order {Id = 19, Price = 91},
};
expected.ToExpectedObject().ShouldEqual(actual);
}
//回傳的資料的PROPERITY很多,但是我們只想比其中幾項
[Test]
public void PartialCompare_Customer_Birthday_And_Order_Price()
{
var actual = customerRepo.GetComposedCustomer();
//有自定型別的一定要改成匿名型別
var expected = new
{
Birthday = new DateTime(1999, 9, 9),
Order = new {Price = 91},
};
//使用匿名型別 去比較以expected為主去比較相對應的actual是否相同
expected.ToExpectedObject().ShouldMatch(actual);
}
}
寫測試的規則
測試程式不含商業邏輯,所有的測試都應該是直述句
不應包含以下的元素:
- prod business logic
- 不含if, else, switch case等邏輯程式碼
- 更不含try..catch
- 不含for, while, foreach, do..while
善用assertion package
- C#: expectedObjects,FluentAssertions
- Java: Assert J
不要攤開properity做比較
[Test]
public void Divide_Zero()
{
var calculator = new Calculator();
var actual = calculator.Divide(5, 0);
Action action = () =>
{
calculator.Divide(5, 0);
};
action.Should().Throw
//never use try/catch in unit test
}
寫測試一定要重構,不然在測試需求異動時和寫測試時會太花時間
因此不應該要有太多不會用到的資訊
讓測試的目標的意圖可以很明顯
要如何加快單元測試撰寫的速度很重要,這樣才有可能可以實踐單元測試
沒有時間是個問題,但是我們要去面對如何解決這個問題
要知道怎麼用工具怎麼寫比較快