伪造 API 调用 /w NSubstitute,用于单元测试
faking API calls /w NSubstitute, for unit testing
我收到了很多像下面这样的函数调用,我想对其进行单元测试,但不确定我应该如何处理这些函数..
我只是用真正的 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;
}
您提供的方法不会在更大的系统上运行,而且您实际上更改了原始代码以进行测试。
模拟框架通常用于单元测试。单元测试本身只是功能的一小部分,一个单一的方法。它绝对不涉及服务。
你应该追求的是抽象,你可以简单地模拟你的服务使用的 interface
。
让我们考虑一个简短的例子。你有一个 IBluetoothService
被注入 BluetoothManager
class。该接口将公开一些在测试模式下将被模拟的方法。
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
class 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
。这不仅可以让您在软件开发中拥有可测试而且更易于维护的方法。
我收到了很多像下面这样的函数调用,我想对其进行单元测试,但不确定我应该如何处理这些函数..
我只是用真正的 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;
}
您提供的方法不会在更大的系统上运行,而且您实际上更改了原始代码以进行测试。
模拟框架通常用于单元测试。单元测试本身只是功能的一小部分,一个单一的方法。它绝对不涉及服务。
你应该追求的是抽象,你可以简单地模拟你的服务使用的 interface
。
让我们考虑一个简短的例子。你有一个 IBluetoothService
被注入 BluetoothManager
class。该接口将公开一些在测试模式下将被模拟的方法。
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
class 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
。这不仅可以让您在软件开发中拥有可测试而且更易于维护的方法。