单元测试 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
包含它应该包含的任何内容.
库是执行某些工作单元的实现细节。它应该被完全抽象出来。如果您想 运行 集成测试 ,那是完全不同的测试方式。
美好的一天,
我对以下单元测试感到困惑:
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
包含它应该包含的任何内容.
库是执行某些工作单元的实现细节。它应该被完全抽象出来。如果您想 运行 集成测试 ,那是完全不同的测试方式。