我有一个类的第一个版本
public class GenerateAuthorisationWorkflows : IGenerateAuthorisationWorkflows
{
public IList<Guid> FromDtaObjects(IList<DtaObject> dtaObjects, Employee requestingEmployee)
{
foreach (var dtaObject in dtaObjects) { }
return new List<Guid>();
}
public IList<Guid> FromDtaObjects()
{
return new List<Guid>();
}
}
MSpec测试它
public abstract class specification_for_generate_workflows : Specification<GenerateAuthorisationWorkflows>
{
protected static IWorkflowService workflowService;
Establish context = () => { workflowService = DependencyOf<IWorkflowService>(); };
}
[Subject(typeof(GenerateAuthorisationWorkflows))]
public class when_generate_workflows_is_called_with_a_dta_object_list_and_an_employee : specification_for_generate_workflows
{
static IList<Guid> result;
static IList<DtaObject> dtaObjects;
static Employee requestingEmployee;
Establish context = () =>
{
var mocks = new MockRepository();
var stubDtaObject1 = mocks.Stub<DtaObject>();
var stubDtaObject2 = mocks.Stub<DtaObject>();
var dtaObjectEnum = new List<DtaObject>{stubDtaObject1,stubDtaObject2}.GetEnumerator();
dtaObjects = mocks.Stub<IList<DtaObject>>();
dtaObjects.Stub(x => x.GetEnumerator()).Return(dtaObjectEnum).WhenCalled(x => x.ReturnValue = dtaObjectEnum);
requestingEmployee = mocks.Stub<Employee>();
mocks.ReplayAll();
};
Because of = () => result = subject.FromDtaObjects(dtaObjects, requestingEmployee);
It should_enumerate_the_dta_objects = () => dtaObjects.received(x=> x.GetEnumerator());
It should_call_workflow_host_helper = () => workflowService.AssertWasCalled(x => x.StartWorkflow());
}
使用此配置,我的第一个测试通过,我的第二个测试失败,正如预期的那样。我在类中添加了一个构造函数来注入IWorkflowService
。
public class GenerateAuthorisationWorkflows : IGenerateAuthorisationWorkflows
{
IWorkflowService _workflowService;
GenerateAuthorisationWorkflows(IWorkflowService workflowService)
{
_workflowService = workflowService;
}
public IList<Guid> FromDtaObjects(IList<DtaObject> dtaObjects, Employee requestingEmployee)
{
foreach (var dtaObject in dtaObjects)
{
Guid workflowKey = _workflowService.StartWorkflow();
}
return new List<Guid>();
}
public IList<Guid> FromDtaObjects()
{
return new List<Guid>();
}
}
现在,当我运行测试时,它们在Because
:
System.InvalidOperationException: Sequence contains no elements
at System.Linq.Enumerable.First(IEnumerable`1 source)
at MSpecTests.EmployeeRequestSystem.Tasks.Workflows.when_generate_workflows_is_called_with_a_dta_object_list_and_an_employee.<.ctor>b__4() in GenerateAuthorisationWorkflowsSpecs.cs: line 76
为清楚起见,上面的第76行是:
Because of = () => result = subject.FromDtaObjects(dtaObjects, requestingEmployee);
我试过追踪问题,但没有运气。我已经尝试设置一个不带参数的构造函数,但它引发了同样的错误。我有类似的IoC依赖类,使用MSpec / Rhino Mocks工作正常,我哪里错了?
答案 0 :(得分:1)
Castle Windsor需要公共构造函数来实例化一个类。将public
添加到构造函数可以正确操作。
public class GenerateAuthorisationWorkflows : IGenerateAuthorisationWorkflows
{
IWorkflowService _workflowService;
public GenerateAuthorisationWorkflows(IWorkflowService workflowService)
{
_workflowService = workflowService;
}
public IList<Guid> FromDtaObjects(IList<DtaObject> dtaObjects, Employee requestingEmployee)
{
foreach (var dtaObject in dtaObjects)
{
Guid workflowKey = _workflowService.StartWorkflow();
}
return new List<Guid>();
}
public IList<Guid> FromDtaObjects()
{
return new List<Guid>();
}
}
答案 1 :(得分:0)
private
。这类错误很容易错过!
我还可以看到您的Establish
块过于复杂。您正在测试实现细节而不是行为。例如,你是
GetEnumerator
循环内隐含的foreach
调用。你实际上没有测试你为输入列表中的每个对象获得了一个GUID。如果我是你,我会测试这样的行为......
public class GenerateAuthorisationWorkflows : IGenerateAuthorisationWorkflows
{
private readonly IWorkflowService _service;
public GenerateAuthorisationWorkflows(IWorkflowService service)
{
_service = service;
}
public List<Guid> FromDtaObjects(List<DtaObject> input, Employee requestor)
{
// I assume that the workflow service generates a new key
// per input object. So, let's pretend the call looks like
// this. Also using some LINQ to avoid the foreach or
// building up a local list.
input.Select(x => _service.StartWorkflow(requestor, x)).ToList();
}
}
[Subject(typeof(GenerateAuthorisationWorkflows))]
public class When_generating_authorisation_keys_for_this_input
: Specification<GenerateAuthorisationWorkflows>
{
private static IWorkflowService _service;
private static Employee _requestor = new Employee();
private static List<DtaObject> _input = new List<DtaObject>()
{
new DtaObject(),
new DtaObject(),
};
private static List<Guid> _expected = new List<Guid>()
{
Guid.NewGuid(),
Guid.NewGuid(),
};
private static List<Guid> _actual = new List<Guid>();
Establish context = () =>
{
// LINQ that takes each item from each list in a pair. So
// the service is stubbed to return a specific GUID per
// input DtaObject.
_input.Zip(_expected, (input, output) =>
{
DependencyOf<IWorkflowService>().Stub(x => x.StartWorkflow(_requestor, input)).Return(output);
});
};
Because of = () => _actual = Subject.FromDtaObjects(_input, _requestor);
// This should be an MSpec collection assertion that
// ensures that the contents of the collections are
// equivalent
It should_get_a_unique_key_per_input = _actual.ShouldEqual(_expected);
}