我有很多函数调用,如下所示,我想进行单元测试,但不确定我应该如何处理这些函数..
我只是用真正的URL和API调用来测试它吗?但是之后它不会成为一个真正的单元测试,因为我包含了我无法控制的东西......这让我得出的结论是我必须嘲笑RestClient
?在哪里我需要制作RestClient Foo(ApiUrl + ApiDirectory);
我可以使用NSubtitute
,这是正确的方法吗?
你们会以同样的方式接近吗?或者有这种单元测试的智能方法吗?
// ReSharper disable once InconsistentNaming
public IRestResponse TCAPIconnection( Method b, long c = 0, object d = null)
{
var client = c == 0 ? new RestClient(ApiUrl + ApiDirectory) : new RestClient(ApiUrl + ApiDirectory + c);
var request = new RestRequest(b);
request.AddHeader("Authorization", Token);
if (d != null)
{
request.AddJsonBody(d);
}
var response = client.Execute(request);
return response;
}
答案 0 :(得分:1)
您提供的方法不会在更大的系统上飞行,也不会为了测试目的而实际更改原始代码。
模拟框架通常用于单元测试。单元测试本身只是功能的一小部分,单一方法。它绝对不涉及服务。
您应该选择的是抽象,您可以简单地模拟您的服务使用的interface
。
让我们考虑一个简短的例子。您有一个IBluetoothService
被注入BluetoothManager
课程。该接口将暴露几种在测试模式下将被模拟的方法。
public interface IBluetoothService
{
object GetData();
bool SendData(object request);
}
public class BluetoothAPI : IBluetoothService
{
public object GetData()
{
// API logic to get data.
return new object();
}
public bool SendData(object request)
{
// API logic to send data.
return false;
}
}
在Logger
班级constructor
中,您应该注入IBluetoothService
。
public class Logger
{
private readonly IBluetoothService _bluetoothService;
public Logger(IBluetoothService bluetoothService)
{
_bluetoothService = bluetoothService;
}
public void LogData(string textToLog)
{
if (!_bluetoothService.SendData(textToLog))
throw new ArgumentException("Could not log data");
}
}
所以,既然你的应用程序中有这个抽象级别,你就可以有效地开始测试了它。
public void SmokeTest()
{
var substitute = Substitute.For<IBluetoothService>();
substitute.GetData().Returns(1);
// Swap true with false and test will fail.
substitute.SendData(Arg.Any<object>()).Returns(true);
var sut = new Logger(substitute);
try
{
sut.LogData("Some data to log");
}
catch (ArgumentException ex)
{
Assert.Fail("Mocked API call returned wrong value.");
}
}
NSubstitute
是一个功能强大的工具,如果您在应用程序中拥有正确的体系结构,它可以让您测试所有内容。要获得可测试的代码,您只需要注入interface
即可。这不仅允许您在软件开发中使用可测试但更易于维护的方法。