使用 Moq 和 xUnit 对服务进行单元测试

Unit Testing a Service with Moq & xUnit

抱歉,这可能是一个非常业余的问题,但我很难理解如何正确使用 Moq。作为一个整体,我对单元测试还很陌生,但我想我开始来掌握它。

所以这是我的问题...我有下面的代码片段,它在 Visual Studio 中使用 TestServer,我将其用于单元测试...我正在尝试模拟IGamesByPublisher 以便我的测试不依赖于存储库中的数据(或者模拟 GamesByPublisher 会更好吗?...或者我是否需要两者都做?)

public static TestServerWithRepositoryService => new TestServer(services =>
{
    services.AddScoped<IGamesByPublisher, GamesByPublisher(); 
}).AddAuthorization("fake.account", null);


[Fact] // 200 - Response, Happy Path
public async Task GamesByPublisher_GamesByPublisherLookup_ValidRequestData_Produces200()
{

    // Arrange
    var server = ServerWithRepositoryService;

    // Act
    var response = await server.GetAsync(Uri);

    // Assert
    Assert.NotNull(response);
    Assert.Equal(HttpStatusCode.OK, response.StatusCode);

}

这里是IGamesByPublisher

public interface IGamesByPublisher interface.
{
    Task<IEnumerable<Publisher>> Execute(GamesByPublisherQueryOptions options);
    }
}

我试过了

public static TestServerWithRepositoryService => new TestServer(services =>
{
    services.AddScoped<Mock<IGamesByPublisher>, Mock<GamesByPublisher>>(); 
}).AddAuthorization("fake.account", null);

然后我尝试了

// Not exactly what I attempted, but that code is long gone... 
var mock = new Mock<IGamesByPublisher >();
var foo = new GamesByPublisherQueryOptions();
mock.Setup(x => x.Execute(foo)).Returns(true);

我并没有真正找到关于使用 Moq 的优秀文档,只是 GitHub 上的快速入门指南,我不确定如何应用它(可能是我自己的经验水平有问题...... .).

我显然缺少一些使用 Moq 的基础知识...

你很接近。

public static TestServerWithRepositoryService => new TestServer(services => {
    var mock = new Mock<IGamesByPublisher>();

    var publishers = new List<Publisher>() {
        //...populate as needed
    };

    mock
        .Setup(_ => _.Execute(It.IsAny<GamesByPublisherQueryOptions>()))
        .ReturnsAsync(() => publishers);
    services.RemoveAll<IGamesByPublisher>();
    services.AddScoped<IGamesByPublisher>(sp => mock.Object); 
}).AddAuthorization("fake.account", null);

上面创建了模拟,将其预期行为设置为 return 发布者列表,任何时候 Execute 被调用 GamesByPublisherQueryOptions

然后删除所需接口的所有注册以避免冲突,然后在请求解析接口时将服务注册到 return 模拟。