【问题标题】:Unit testing MVC Controller making calls to a static library calling external API单元测试 MVC 控制器调用静态库调用外部 API
【发布时间】:2015-07-16 17:15:46
【问题描述】:

早安,

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

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,该 API 执行一些工作并返回结果或引发错误。

外部 Api 没有接口或抽象类

我该如何进行单元测试呢? N. B. 我无权更改外部 Api 的设计。

谢谢,

【问题讨论】:

    标签: c# asp.net asp.net-mvc unit-testing static-libraries


    【解决方案1】:

    在代码中使用静态类或方法会使代码难以正确进行单元测试。见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 notWhen to use static classes in C#

    将静态API调用类包装成带有接口的实例类:

    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

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

    • 代码是否使用正确的参数调用库?
    • 该方法是否返回正确的对象?

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

    【讨论】:

    • 感谢您的回答。曾经有人告诉我,你的设计应该只服务于你的主要目标。基本上,您不会将代码调整为“可测试”。静态库在那里是因为不需要它不是静态的。另外,那个控制器使用 Server.Mappath 怎么样?
    • 这是一个广泛的讨论。我认为您确实必须更改您的代码以使其可测试,因为这些利益是相互冲突的:最“密集”或“最小”的代码通常根本不可测试,而您 想要测试它。有许多模式可以帮助您使代码更具可重用性和可测试性。我根本不喜欢静态类,尤其是当它们包含的方法有副作用时(在这种情况下,调用 Web 服务,这不应该在测试期间发生)。经常使用静态类“所以我们不必使用new”,这不是使用静态的借口。
    • 至于Server.MapPath(),见Unit testing for Server.MapPath
    • 嗨。我有一个question in SO。你能帮我吗,因为它非常紧急。我真的会为您提供帮助。
    • 我支持@CodeCaster。测试您的代码您的主要目标之一。
    【解决方案2】:

    库是执行某些工作单元的实现细节。应该完全抽象出来。如果您想运行集成测试,那完全是另一种测试风格。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 2020-05-22
      • 2022-12-05
      • 1970-01-01
      • 2021-08-02
      相关资源
      最近更新 更多