如何在C#中Mock Firebase?WPF项目XUnit单元测试遇错
解决XUnit Mock FirebaseClient时的可选参数错误
错误根源
你碰到的An expression tree may not contain a call or invocation that uses optional arguments错误,是因为Moq在构建表达式树时,不支持调用包含可选参数的方法。你的代码里直接给PostAsync传了null作为第三个参数,而这个参数原本是可选的,Moq无法解析这种写法。
修复方案
1. 调整Mock Setup的方法调用
不要直接在Setup里用null替代可选参数,改用Moq的It.IsAny<T>来匹配参数类型(如果知道参数具体类型的话,尽量精准匹配)。假设PostAsync的第三个参数是CancellationToken类型,修改后的Setup代码如下:
firebaseClientMock.Setup(f => f.Child("Patients").PostAsync(It.IsAny<string>(), It.IsAny<Patient>(), It.IsAny<CancellationToken>())) .ReturnsAsync(true);
如果不确定参数类型,也可以用It.IsAny<object>()临时替代,但建议尽量匹配实际参数类型,避免后续测试出现意外问题。
2. 简化FirebaseObject创建(可选优化)
你用反射创建私有构造的FirebaseObject其实没必要,直接用Moq Mock这个对象更简洁:
var firebaseObjectMock = new Mock<FirebaseObject<Patient>>(); firebaseObjectMock.SetupGet(x => x.Object).Returns(patient);
3. 完整修复后的测试代码
[Fact] public async Task SavePatientDetails_Success() { var firebaseClientMock = new Mock<FirebaseClient>(MockBehavior.Strict); var patientService = new PatientService(firebaseClientMock.Object); var patient = new Patient { Id = "123", Name = "John", Surname = "Doe", FatherName = "Mark", PatientGender = "Male", Dob = new DateTime(2001, 1, 1), Address = "John Doe Avenue 1", Phone = "+386 123 456 789", Email = "john.doe@emailprovider.com" }; // 修正PostAsync的Setup,规避可选参数问题 firebaseClientMock.Setup(f => f.Child("Patients").PostAsync(It.IsAny<string>(), It.IsAny<Patient>(), It.IsAny<CancellationToken>())) .ReturnsAsync(true); var result = await patientService.SavePatientDetails(patient); Assert.IsTrue(result); // 可选:验证目标方法是否被正确调用一次 firebaseClientMock.Verify(f => f.Child("Patients").PostAsync(It.IsAny<string>(), It.IsAny<Patient>(), It.IsAny<CancellationToken>()), Times.Once); }
额外提示
- 若不确定
PostAsync的参数类型,可通过Firebase SDK的IntelliSense提示或源码确认,确保It.IsAny<T>的T与实际参数类型一致。 MockBehavior.Strict要求所有被调用的方法必须提前Setup,若不确定Service会调用哪些FirebaseClient方法,可改用MockBehavior.Loose降低测试的严格性。- 单元测试核心是验证
PatientService的业务逻辑,无需Mock Firebase的全部实现,只需要MockSavePatientDetails用到的方法即可。
内容的提问来源于stack exchange,提问作者Vunjash
相关产品推荐
相关产品推荐

