3️⃣ Configuring Mock Method Return Values
3.1 Configuring Mock Object Method Return Values
- Setup cho method
ValidatecủaIIdentityVerifier:
mockIdentityVerifier.Setup(x => x.Validate("Sarah",
25,
"133 Pluralsight Drive, Draper, Utah"))
.Returns(true);
- Nếu đổi tên
"Sarah"->"Sarah 2", method sẽ trả vềfalsevì setup không match:
mockIdentityVerifier.Setup(x => x.Validate("Sarah 2", 25, "133 Pluralsight Drive, Draper, Utah"))
.Returns(true);
- Test case đầy đủ:
[Test]
public void Accept()
{
LoanProduct product = new LoanProduct(99, "Loan", 5.25m);
LoanAmount amount = new LoanAmount("USD", 200_000);
var application = new LoanApplication(42,
product,
amount,
"Sarah",
25,
"133 Pluralsight Drive, Draper, Utah",
65_000);
var mockIdentityVerifier = new Mock<IIdentityVerifier>();
mockIdentityVerifier.Setup(x => x.Validate("Sarah", 25, "133 Pluralsight Drive, Draper, Utah")).Returns(true);
var mockCreditScorer = new Mock<ICreditScorer>();
var sut = new LoanApplicationProcessor(mockIdentityVerifier.Object,
mockCreditScorer.Object);
sut.Process(application);
Assert.That(application.GetIsAccepted(), Is.True);
}
3.2 Argument Matching in Mocked Methods
- Sử dụng
It.IsAny<T>()bỏ qua giá trị cụ thể, chỉ kiểm tra kiểu:
mockIdentityVerifier.Setup(x => x.Validate(It.IsAny<string>(),
It.IsAny<int>(),
It.IsAny<string>()))
.Returns(true);
- Test case:
[Test]
public void Accept()
{
var mockIdentityVerifier = new Mock<IIdentityVerifier>();
mockIdentityVerifier.Setup(x => x.Validate(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<string>())).Returns(true);
var application = new LoanApplication(...);
var sut = new LoanApplicationProcessor(mockIdentityVerifier.Object, new Mock<ICreditScorer>().Object);
sut.Process(application);
Assert.That(application.GetIsAccepted(), Is.True);
}
- 💡 Lưu ý:
.Returns()luôn trả về giá trị setup, không phụ thuộc parameter.
3.3 Mocking Methods with out Parameters
- Khi function có parameter
out:
void Validate(string applicantName, int applicantAge, string applicantAddress, out bool isValid);
- Setup:
bool isValidOutValue = true;
mockIdentityVerifier.Setup(x => x.Validate("Sarah",
25,
"133 Pluralsight Drive, Draper, Utah",
out isValidOutValue));
- Test case đầy đủ:
[Test]
public void Accept()
{
var mockIdentityVerifier = new Mock<IIdentityVerifier>();
bool isValidOutValue = true;
mockIdentityVerifier.Setup(x => x.Validate("Sarah", 25, "Address", out isValidOutValue));
var sut = new LoanApplicationProcessor(mockIdentityVerifier.Object, new Mock<ICreditScorer>().Object);
sut.Process(application);
Assert.That(application.GetIsAccepted(), Is.True);
}
3.4 Mocking Methods with ref Parameters
- Function có parameter
ref:
void Validate(string applicantName, int applicantAge, string applicantAddress, ref IdentityVerificationStatus status);
- Setup dùng delegate và
.Callback():
delegate void ValidateCallback(string name, int age, string addr, ref IdentityVerificationStatus status);
mockIdentityVerifier
.Setup(x => x.Validate("Sarah", 25, "Address", ref It.Ref.IsAny<IdentityVerificationStatus>()))
.Callback(new ValidateCallback((string n, int a, string addr, ref IdentityVerificationStatus s) =>
s = new IdentityVerificationStatus(true)));
- Test case đầy đủ:
[Test]
public void Accept()
{
var mockIdentityVerifier = new Mock<IIdentityVerifier>();
mockIdentityVerifier.Setup(x => x.Validate("Sarah", 25, "Address", ref It.Ref.IsAny<IdentityVerificationStatus>()))
.Callback(new ValidateCallback((string n, int a, string addr, ref IdentityVerificationStatus s) =>
s = new IdentityVerificationStatus(true)));
var sut = new LoanApplicationProcessor(mockIdentityVerifier.Object, new Mock<ICreditScorer>().Object);
sut.Process(application);
Assert.That(application.GetIsAccepted(), Is.True);
}
3.5 Configuring Mock Methods to Return Null
- Interface giả:
public interface INullExample
{
string SomeMethod();
}
- Nếu không
.Returns(), mặc định trảnull:
[Test]
public void NullReturnExample()
{
var mock = new Mock<INullExample>();
mock.Setup(x => x.SomeMethod());
string mockReturnValue = mock.Object.SomeMethod();
Assert.That(mockReturnValue, Is.Null);
}
4️⃣ Working with Mock Properties
4.1 Return a Specified Value
mockCreditScorer.Setup(x => x.Score).Returns(300);
4.2 Manually Mocking Property Hierarchies
var mockScoreValue = new Mock<ScoreValue>();
mockScoreValue.Setup(x => x.Score).Returns(300);
var mockScoreResult = new Mock<ScoreResult>();
mockScoreResult.Setup(x => x.ScoreValue).Returns(mockScoreValue.Object);
var mockCreditScorer = new Mock<ICreditScorer>();
mockCreditScorer.Setup(x => x.ScoreResult).Returns(mockScoreResult.Object);
4.3 Auto Mocking Property Hierarchies
- Nếu property là
virtual, có thể viết ngắn:
mockCreditScorer.Setup(x => x.ScoreResult.ScoreValue.Score).Returns(300);
DefaultValue.Mockcho các property con mặc định không null:
var mockCreditScorer = new Mock<ICreditScorer> { DefaultValue = DefaultValue.Mock };
4.4 Track Changes for Property
mockCreditScorer.SetupProperty(x => x.Count);
mockCreditScorer.SetupProperty(x => x.Count, 10);
4.5 Track All Properties
mockCreditScorer.SetupAllProperties();
5️⃣ Checking That Mock Methods and Properties Are Used
5.1 Verify Method (No Parameters)
mockIdentityVerifier.Verify(x => x.Initialize());
5.2 Verify Method Called with Parameters
mockCreditScorer.Verify(x => x.CalculateScore("Sarah", "133 Pluralsight Drive, Draper, Utah"));
5.3 Verify Number of Calls
mockCreditScorer.Verify(x => x.CalculateScore("Sarah", "Address"), Times.Once);
5.4 Verify Property Get/Set
mockCreditScorer.VerifyGet(x => x.ScoreResult.ScoreValue.Score, Times.Once);
mockCreditScorer.VerifySet(x => x.Count = It.IsAny(), Times.Once);
mockCreditScorer.VerifySet(x => x.Count = 1);
5.5 Verify No Unexpected Calls
mockIdentityVerifier.VerifyNoOtherCalls();
6️⃣ Using Partial Mocks and Advanced Mocking Techniques
6.1 Understanding Strict Mocks
Loosemock mặc định không throw exception,Strictbắt buộc setup tất cả method.
var mockIdentityVerifier = new Mock<IIdentityVerifier>(MockBehavior.Strict);
6.2 Throwing Exceptions
mockCreditScorer.Setup(x => x.CalculateScore(It.IsAny<string>(), It.IsAny<string>()))
.Throws(new InvalidOperationException("Test Exception"));
6.3 Raising Events
- Moq có thể raise event từ mock object.
6.4 Understanding Partial Mocks
- Chỉ mock một phần class, phần còn lại dùng implementation thật.
6.5 Mocking Nondeterministic Code
- Mock
DateTime.Nowhoặc các giá trị random.
6.6 Mocking Protected Members
- Partial mock có thể mock protected methods hoặc properties.
6.7 Alternatives to Partial Mocks
- Dùng dependency injection, wrapper, hoặc helper class thay thế.
💡 Tổng kết:
- Moq + NUnit cho phép kiểm tra unit test chi tiết, từ setup method, ref/out parameters, property tracking, verify method/property, đến xử lý exception & event.
- Dùng đúng Strict/Loose, It.IsAny(), SetupProperty, SetupAllProperties sẽ giúp unit test chính xác và tránh lỗi ngầm.