单元测试 MVC 控制器调用静态库调用外部 API

Unit testing MVC Controller making calls to a static library calling external API

美好的一天,

我对以下单元测试感到困惑:

1. MVC 控制器:

[HttpGet]
public async Task<PartialViewResult> DoExternalCallsAsync()
{
    var model = new MyModel();

    await MyStaticLibrary.DoExternalWorkAsync(Server.MapPath("~\") + "WorkSource.txt", model);

    return PartialView("_MyResults", model);
}

2。静态库:

public static async Task DoExternalWorkAsync(string sourcePath, MyModel model)
        {
            var externalCalls =
                System.IO.File.ReadAllLines(sourcePath)
                .Where(line => (!string.IsNullOrEmpty(line) && line.First() != '#'))
                .Select(p => DoExternalCall(p, model));

            await Task.WhenAll(externalCalls);


        }



 private static async Task DoExternalCall(string urlPath, MyModel model)
            {
                var result = await GetExternalApiResultAysnc(urlPath);

                // some code here...



                return;
            }

基本上,控制器所做的就是调用一个外部 API,它会做一些工作,returns 一个结果或抛出一个错误。

没有与外部 Api 的接口或抽象 类

我该如何进行单元测试? N. B. 我不能随意更改外部 Api 的设计。

谢谢,

在代码中使用静态 classes 或方法会使该代码难以进行正确的单元测试。参见 Is static universally “evil” for unit testing and if so why does resharper recommend it?, Static class/method/property in unit test, stop it or not, When to use static classes in C#

将静态 API 调用 class 包装到具有接口的实例 class 中:

public interface IMyLibrary
{
    Task DoExternalWorkAsync();
}

public class MyStaticLibrary : IMyLibrary
{
    public async Task DoExternalWorkAsync(string sourcePath, MyModel model)
    {
        return await MyStaticLibrary.DoExternalWorkAsync(sourcePath, model);
    }
}

那你可以inject an instance into the controller's constructor.

因为在这个控制器操作方法中唯一应该进行单元测试的是:

  • 代码是否使用正确的参数调用库?
  • 方法 return 是正确的对象吗?

在测试期间,您可以在控制器中注入一个模拟的 IMyLibrary 并验证控制器是否正确调用模拟,并且您可以验证结果是一个 PartialViewResult 包含它应该包含的任何内容.

库是执行某些工作单元的实现细节。它应该被完全抽象出来。如果您想 运行 集成测试 ,那是完全不同的测试方式。