C# 单元测试不显示异步/等待的代码覆盖率

C# 单元测试不显示异步/等待的代码覆盖率,c#,unit-testing,asynchronous,moq,C#,Unit Testing,Asynchronous,Moq,我使用的是vs2017,没有一个单元测试显示代码覆盖率。我正在使用async/await和MOQ [TestMethod] [TestCategory("SeriesRepository")] public void GetSeriesAsyncShouldReturnSeriesId12345() { var repositoryMock = new Mock<ISeriesRepository>(); var seriesId = "12345"; va

我使用的是vs2017,没有一个单元测试显示代码覆盖率。我正在使用async/await和MOQ

[TestMethod]
[TestCategory("SeriesRepository")]
public void GetSeriesAsyncShouldReturnSeriesId12345()
{
    var repositoryMock = new Mock<ISeriesRepository>();

    var seriesId = "12345";
    var channel = 75864;            

    var mockSeries = new Mock<ISeries>();
    mockSeries.SetupGet(x => x.SeriesId).Returns("12345");

    repositoryMock
        .Setup(x => x.GetSeriesAsync(seriesId, channel))
        .ReturnsAsync(mockSeries.Object);

    var result = repositoryMock.Object.GetSeriesAsync(seriesId, channel).Result;

    result.SeriesId.Should().Be(seriesId);
}
[TestMethod]
[测试类别(“系列报告”)]
public void GetSeriesAsynchshouldReturnSeriesID12345()
{
var repositoryMock=new Mock();
var seriesId=“12345”;
var通道=75864;
var mockSeries=new Mock();
SetupGet(x=>x.SeriesId).Returns(“12345”);
重置模拟
.Setup(x=>x.GetSeriesAsync(seriesId,通道))
.ReturnsAsync(mockSeries.Object);
var result=repositoryMock.Object.GetSeriesAsync(seriesId,channel.result);
result.SeriesId.Should().Be(SeriesId);
}

无需等待repositoryMock安装完成。因此,您的测试用例将在异步调用完成之前结束

通过添加以下内容确保您等待:

repositryMock.setup(...).ReturnsAsync(...).GetAwaiter().GetResult();


这应该可以解决您的问题。

第一个事实是,您实际上并没有在测试中测试任何东西,因为您只是创建模拟并调用模拟

您只是在测试mocking框架是否如广告所示工作

其次,测试也可以是异步的,以允许测试按顺序进行

[TestMethod]
[TestCategory("SeriesRepository")]
public async Task GetSeriesAsyncShouldReturnSeriesId12345() {
    var repositoryMock = new Mock<ISeriesRepository>();

    var seriesId = "12345";
    var channel = 75864;            

    var mockSeries = new Mock<ISeries>();
    mockSeries.Setup(_ => _.SeriesId).Returns(seriesId);

    repositoryMock
        .Setup(_ => _.GetSeriesAsync(seriesId, channel))
        .ReturnsAsync(mockSeries.Object);

    var result = await repositoryMock.Object.GetSeriesAsync(seriesId, channel);

    result.SeriesId.Should().Be(seriesId);
}
[TestMethod]
[测试类别(“系列报告”)]
公共异步任务GetSeriesAsyncShouldReturnSeriesId12345(){
var repositoryMock=new Mock();
var seriesId=“12345”;
var通道=75864;
var mockSeries=new Mock();
mockSeries.Setup(=>u.SeriesId).Returns(SeriesId);
重置模拟
.Setup(=>u.GetSeriesAsync(seriesId,通道))
.ReturnsAsync(mockSeries.Object);
var result=await repositoryMock.Object.GetSeriesAsync(seriesId,channel);
result.SeriesId.Should().Be(SeriesId);
}
假设发生的情况是,为了验证某些所需的行为,您模拟了被测试目标的依赖项,使其行为符合预期

假设我们想测试一个类的目标方法

public class SeriesService {
    private readonly ISeriesRepository repository;

    public SeriesService(ISeriesRepository repository
        this.repository = repository;
    }

    public async Task<ISeries> GetSeries(string seriesId, int channel) {
        var series = await repository.GetSeriesAsync(seriesId, channel);

        //...do some other stuff

        return series;
    }
}
公共类服务{
私有只读存储库;
公共服务(iSeries)存储库
this.repository=存储库;
}
公共异步任务GetSeries(字符串序列ID,int通道){
var series=await repository.GetSeriesAsync(seriesId,channel);
//…做些别的事
返回序列;
}
}
然后,一个示例测试将如下所示

[TestMethod]
[TestCategory("SeriesRepository")]
public async Task TargetMethodShouldReturnSeriesId12345() {
    //Assert
    var repositoryMock = new Mock<ISeriesRepository>();

    var seriesId = "12345";
    var channel = 75864;            

    var mockSeries = new Mock<ISeries>();
    mockSeries.Setup(_ => _.SeriesId).Returns(seriesId);

    repositoryMock
        .Setup(_ => _.GetSeriesAsync(seriesId, channel))
        .ReturnsAsync(mockSeries.Object);

    var target = new SeriesService(repositoryMock.Object);

    //Act
    var result = await target.GetSeries(seriesId, channel);

    //Assert
    result.Should().NotBeNull();
    result.SeriesId.Should().Be(seriesId);
}
[TestMethod]
[测试类别(“系列报告”)]
公共异步任务targetMethod应返回Seriesid12345(){
//断言
var repositoryMock=new Mock();
var seriesId=“12345”;
var通道=75864;
var mockSeries=new Mock();
mockSeries.Setup(=>u.SeriesId).Returns(SeriesId);
重置模拟
.Setup(=>u.GetSeriesAsync(seriesId,通道))
.ReturnsAsync(mockSeries.Object);
var target=newserieservice(repositoryMock.Object);
//表演
var result=await target.GetSeries(seriesId,channel);
//断言
result.Should().NotBeNull();
result.SeriesId.Should().Be(SeriesId);
}

您似乎只是在调用模拟方法,这不会导致调用任何非测试代码。您希望此测试包含哪些未显示为已覆盖的代码?您是否在问为什么单元测试代码未显示为已覆盖,或者为什么实际逻辑代码未显示为已覆盖?如果是前者,请确保您的测试s实际运行。如果是后者,您在哪里调用实际逻辑代码?似乎您正在设置模拟,然后确保模拟按模拟的方式运行。您要在此处测试的实际逻辑代码是什么?您的意思是,除了读取
.Result
这是一个阻塞调用之外?(如果确实涉及任何任务,则应为阻塞调用)。是的,我们应该进行此阻塞调用;以确保在下一次调用发生之前执行所有涉及的任务。如果您的测试方法是异步的,那么您可以等待它而不是阻塞调用。我对TargetClass的类型感到困惑。TargetClass与我的SeriesService类类似。我的SeriesService类需要ISeriesRepository待注入。@user3582849可能是正确的。显示该类的示例,以便我们可以为其制定一个独立的单元测试。谢谢。完成了。这算是存储库测试还是服务测试?我创建了一个名为SeriesRepositoryTest的测试类,如果这是测试Repository,我应该如何测试服务ice layer?@user3582849此单元测试在隔离状态下测试
SerieService
。本例中的存储库是一个显式的依赖项,它被模拟,以便允许在隔离状态下测试被测系统,而不必使用实际的存储库实现。这是针对web api的,我还有一个控制器。Wh至少,您建议用这个进行单元测试吗?编写一个测试控制器的单元测试是否有意义?iSeries服务被注入到控制器中。
public class SeriesService {
    private readonly ISeriesRepository repository;

    public SeriesService(ISeriesRepository repository
        this.repository = repository;
    }

    public async Task<ISeries> GetSeries(string seriesId, int channel) {
        var series = await repository.GetSeriesAsync(seriesId, channel);

        //...do some other stuff

        return series;
    }
}
[TestMethod]
[TestCategory("SeriesRepository")]
public async Task TargetMethodShouldReturnSeriesId12345() {
    //Assert
    var repositoryMock = new Mock<ISeriesRepository>();

    var seriesId = "12345";
    var channel = 75864;            

    var mockSeries = new Mock<ISeries>();
    mockSeries.Setup(_ => _.SeriesId).Returns(seriesId);

    repositoryMock
        .Setup(_ => _.GetSeriesAsync(seriesId, channel))
        .ReturnsAsync(mockSeries.Object);

    var target = new SeriesService(repositoryMock.Object);

    //Act
    var result = await target.GetSeries(seriesId, channel);

    //Assert
    result.Should().NotBeNull();
    result.SeriesId.Should().Be(seriesId);
}