服务类中有这两种方法
public class PatientService : IPatientService
{
private readonly IRestClient _restClient;
private readonly IAppSettings _appSettings;
public PatientService(IRestClient restClient, IAppSettings appSettings)
{
_restClient = restClient;
_appSettings = appSettings;
}
public async Task<IList<PatientViewModel>> GetPatients(int wardId)
{
var url = _appSettings.Server + _appSettings.PatientServiceEndPoint + wardId;
var token = _appSettings.Token;
return GetPatientList(await _restClient.GetAsync<List<PatientInfo>>(url, token));
}
public IList<PatientViewModel> GetPatientList(IList<PatientInfo> patientInfoList)
{
return patientInfoList.Select(p => new PatientViewModel(p)).ToList();
}
}
我需要将此代码添加到Xunit.cs中。怎么做?
我已经实现了这一点,但我不知道如何进行。
private readonly PatientListPageViewModel _patientListPageViewModel;
private readonly Mock<IPatientService> _patient;
public PatientServiceTests()
{
_patient = new Mock<IPatientService>();
_patientListPageViewModel = new PatientListPageViewModel(_patient.Object);
}
[Fact]
public void GetListByWard_PassingWardId_GetPatientsCountAccordingToWardId()
{
}
这是我试图做的。如何将服务中的这两种方法转换为可测试的?
答案 0 :(得分:0)
您确实嘲笑了一下。被模拟的不是被测组件,而是其依赖项。进行单元测试时,您想单独测试一个单元。如果您对PatientListPageViewModel
进行了单元测试,那么您的模拟案例是正确的,但是由于您的测试类名为PatientServiceTests
,所以我认为您确实想测试PatientService
。如果您想测试前者,则完全可以模拟IPatientService
,但是在测试PatientService
时,IRestClient
和IAppSettings
应该被模拟
public PatientServiceTests()
{
_restClientMock = new Mock<IRestClient>();
_appSettingsMock = new Mock<IAppSettings>();
_patientService = new PatientService(_restClientMock.Object, _appSettingsMock.Object);
}
您的测试可能类似于
[Fact]
public async Task ReturnsCorrectPatientList() // async supported as of xUnit 1.9
{
// set up the mock
_restClientMock.SetUp(restClient => restClient.GetAsync<List<Patient>>(It.IsAny<string>(), It.IsAny<string>())
.Returns(() => Task.FromResult(/* what patients it shall return */));
var result = await _patientService.GetPatients(0);
// compare whether the returned result matches your expectations
}
如果要测试URL的格式是否正确,可以使用Verify
[Theory]
[InlineData("SERVER", "ENDPOINT", 12, "1234", "SERVERENDPOINT12")]
[InlineData("https://localhost:65000", "/patients/", 5, https://localhost:65000/patients/5")]
public void TestWhetherCorrectUrlIsCalled(string server, string endpoint, int wardId, string token, string expectedUrl)
{
_appSettingsMock.SetupGet(appSettings => appSettings.Server).Returns(server);
_appSettingsMock.SetupGet(appSettings => appSettings.PatientServiceEndPoint).Returns(endpoint);
_appSettingsMock.SetupGet(appSettings => appSettings.Token).Returns(token);
_restClientMock.SetUp(restClient => restClient.GetAsync<List<Patient>>(It.IsAny<string>(), It.IsAny<string>())
.Returns(() => Task.FromResult(new List<Patient>()));
// we do not need the result
await _patientService.GetPatients(wardId);
_restClientMock.Verify(restClient => restClient.GetAsync<List<Patient>>(exptectedUrl, token), Times.Once);
}
在这种情况下,我们正在设置IRestClient
,因为否则它将返回null
。 await null
会导致您的测试失败。调用GetPatients
之后,我们将使用Verify
来验证是否已使用正确的参数调用了GetAsync
。如果尚未调用,则会抛出Verify
并且测试将失败。 Times.Once
意味着GetAsync
应该被调用过一次,并且只能被调用一次。
附带说明:Viewmodels仅在用户界面的上下文中具有含义。服务应该是独立的,因此不会像您那样返回视图模型,而是返回POCO(或域模型)。在这种情况下,您的服务界面应为
public interface IPatientService
{
public async Task<IList<Patient>> GetPatients(int wardId);
// ...
}