我使用Typemock进行单元测试。在我的情况下,我为一个执行平面文件数据处理的程序编写测试。为了对该程序进行单元测试,我已经编写了一些实现相同接口的存根类,而实际版本使用的是,但不是写入文件系统,而是包含他们写入的内部字符串。
现在我试图让Typemock用测试中的stub变体替换类的实际版本,但是它给了我以下错误: System.InvalidOperationException:Nullable对象必须具有值。
这是我试图用我的存根替换的实际版本(包含更多但错误不在这些行上):
public class BatchRepository : IBatchRepository
{
private readonly string _connectionStringName;
public BatchRepository(string connectionStringName) <-- Error triggers on this line
{
_connectionStringName = connectionStringName;
}
}
存根类:
public class BatchRepositoryStub : IBatchRepository
{
private readonly string _connectionStringName;
public BatchRepositoryStub(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
}
测试类和我的测试方法:
[TestClass]
public class InputTest
{
// Variables
private IBatchRepository _batchRepository;
private ICommunicatieproductRepository _communicatieproductRepository;
// Constants
private const string ConnectionStringName = "Test";
private const string InputFileLocation = "Temp";
private const string ArchiefLocation = "Temp";
private const string ErrorLocation = "Temp";
private const string LoggingLocation = "Temp";
private const int BatchGrootte = 1000;
// Use TestInitialize to run code before running each test
[TestInitialize()]
public void Initialize()
{
_batchRepository = new BatchRepositoryStub(ConnectionStringName);
_communicatieproductRepository = new CommunicatieproductRepositoryStub(ConnectionStringName);
}
[TestMethod]
public void CMBatch_FDInput_NewFileErrorOnEmptyRelatienummer()
{
// Arrange
Isolate.Swap.NextInstance<IBatchRepository>().With(_batchRepository);
Isolate.Swap.NextInstance<ICommunicatieproductRepository>().With(_communicatieproductRepository);
var inputFileProcessor = new InputFileProcessor(InputFileLocation, ArchiefLocation, ErrorLocation, LoggingLocation, BatchGrootte, ConnectionStringName);
}
}
实际过程,这会触发错误
public class InputFileProcessor
{
private readonly string _inputFileLocation;
private readonly string _archiefLocation;
private readonly string _errorLocation;
private readonly string _loggingLocation;
private readonly int _batchGrootte;
private readonly IBatchRepository _batchRepository;
private readonly ICommunicatieproductRepository _communicatieproductRepository;
/// <summary>
/// Constructor
/// </summary>
public InputFileProcessor(string inputFileLocation, string archiefLocation, string errorLocation, string loggingLocation, int batchGrootte, string connectionStringName)
{
_inputFileLocation = inputFileLocation;
_archiefLocation = archiefLocation;
_errorLocation = errorLocation;
_loggingLocation = loggingLocation;
_batchGrootte = batchGrootte;
_batchRepository = new BatchRepository(connectionStringName);
_communicatieproductRepository = new CommunicatieproductRepository(connectionStringName);
}
}
当从InputFileProcessor的构造函数调用时,错误在BatchRepository的构造函数上触发。起初我认为参数connectionstringname为null,但事实并非如此。为什么它最终会在那条线上结束?使用交换实例方法,我认为它甚至不会到达那里,但最终会进入存根类。我认为我的交换实例的实现有问题,但我无法弄清楚。
我知道这样的测试可能不完全是单元测试的内容,但它是测试程序输出和输入的最简单方法。例如,我需要确保无效文件触发相应的错误。能够轻松更改输入使得更易于管理。
答案 0 :(得分:1)
当然可以使用Typemock完成: - )
使用Swap.CallsOn(object)
转发对存根的调用(这些调用不需要分配)。
参见示例:
// grab future
var futureInstanceHandle = Isolate.Fake.NextInstance<BatchRepository>();
// swap (ingoring type hiearchy)
Isolate.Swap.CallsOn(futureInstanceHandle).WithCallsTo(_batchRepositorystub);
在版本8中,您可以使用Fake.NextInstance<IBatchRepository>
作为接口!这将抓住实现IBatchRepository
的第一个实例 - 非常酷呃。
p.s我在Typemock工作。
答案 1 :(得分:0)
显然,这是Typemock无法完成的事情。它本质上是测试太大的代码块,这不完全是单元测试。 目前,我已经使用公司内部使用的变体重构了代码。