使用 NSubstitute 驗證 Mock 物件的方法傳入參數
在有些測試情境我們想要驗證是否有呼叫某個相依物件的方法,並且傳入了我們預期的參數,透過 NSubstitute 可以簡單的做驗證
我有一個待測物件 MyClass,相依了一個基於 IDbOperator 的類別
public class MyClass
{
private readonly IDbOperator _dbOperator;
public MyClass(IDbOperator dbOperator)
{
_dbOperator = dbOperator;
}
public void Action(int id)
{
_dbOperator.Create(new Member()
{
Id = id,
Name = $"Name_{id}",
});
}
}
若我想要驗證當執行 Action(1) 時,_dbOperator的 Create 也會收到一個 id = 1的值,我可以這樣寫
public class MyTest
{
[Fact]
public void Index()
{
var dbOperator = Substitute.For<IDbOperator>();
var myClass = new MyClass(dbOperator);
myClass.Action(1);
dbOperator.Received(1).Create(Arg.Is<Member>(r => r.Id == 1));
}
}
若連 Name 也要驗證,可以直接加上 &&
dbOperator.Received(1).Create(Arg.Is<Member>(r => r.Id == 1 && r.Name == "Name_1"));
若 Member 的 Property 數量相當多時,這樣的寫法就不太適當了,這時候可以換個方式,直接取出整個參數來做驗證,重點會在 Arg.Do<T>()
[Fact]
public void Index()
{
var member = default(Member);
_dbOperator.Create(Arg.Do<Member>(r => member = r));
_myClass.Action(1);
_dbOperator.Received(1).Create(Arg.Any<Member>());
member.Should().BeEquivalentTo(new
{
Id = 1,
Name = "Name_1"
});
}
每個一段時間都會忘記 Arg.Do 怎麼用,筆記起來方便快速回憶
在有些測試情境我們想要驗證是否有呼叫某個相依物件的方法,並且傳入了我們預期的參數,透過 NSubstitute 可以簡單的做驗證
我有一個待測物件 MyClass,相依了一個基於 IDbOperator 的類別
public class MyClass { private readonly IDbOperator _dbOperator; public MyClass(IDbOperator dbOperator) { _dbOperator = dbOperator; } public void Action(int id) { _dbOperator.Create(new Member() { Id = id, Name = $"Name_{id}", }); } }
若我想要驗證當執行 Action(1) 時,_dbOperator的 Create 也會收到一個 id = 1的值,我可以這樣寫
public class MyTest { [Fact] public void Index() { var dbOperator = Substitute.For<IDbOperator>(); var myClass = new MyClass(dbOperator); myClass.Action(1); dbOperator.Received(1).Create(Arg.Is<Member>(r => r.Id == 1)); } }
若連 Name 也要驗證,可以直接加上 &&
dbOperator.Received(1).Create(Arg.Is<Member>(r => r.Id == 1 && r.Name == "Name_1"));
若 Member 的 Property 數量相當多時,這樣的寫法就不太適當了,這時候可以換個方式,直接取出整個參數來做驗證,重點會在 Arg.Do<T>()
[Fact] public void Index() { var member = default(Member); _dbOperator.Create(Arg.Do<Member>(r => member = r)); _myClass.Action(1); _dbOperator.Received(1).Create(Arg.Any<Member>()); member.Should().BeEquivalentTo(new { Id = 1, Name = "Name_1" }); }
每個一段時間都會忘記 Arg.Do 怎麼用,筆記起來方便快速回憶