[英]Application Layer Testing
I want to test class of Application Layer and not sure about what is better. 我想测试应用程序层的类,不确定是否更好。 I have class of Domain Model is Task, eg
我有类的领域模型是任务,例如
class Task {
private Clock clock;
public Guid Id {get; private set;}
public string Name {get; set;}
public DateTime StartedDate {get; private set;}
public Task(Guid id, string name, Clock pClock) {
Id = id;
Name = name;
clock = pClock;
StartedDate = clock.Now();
}
}
interface Clock
{
DateTime Now {get;}
}
So I want to test CreateTask method of WorkManagementService class. 因此,我想测试WorkManagementService类的CreateTask方法。 I can not understand what I should test.
我不明白我应该测试什么。 Suppose, I write test
假设我写测试
TestCreateTaskShouldReturnTaskIdWasCreated()
{
Guid taskId = Guid.Empty;
TaskRepository repository = Substitute.For<TaskRepository>();
repsitory.Add(Arg.Do<Task>(taskArgument => taskId = taskArgument.Id));
var service = new WorkManagementService(repository);
var createdTaskId = service.CreateTask("task name");
Assert.AreNotEqual(Guid.Empty, createdTaskId);
Assert.AreEqual(taskId, createdTaskId);
}
So, I'm not sure if it's good practice. 因此,我不确定这是否是一个好习惯。 CreateTask method uses Task constructor to create Task and some implementation of Clock interface, so WorkManagementService class depends on them.
CreateTask方法使用Task构造函数创建Task和Clock接口的某些实现,因此WorkManagementService类依赖于它们。 Is a good way?
是个好方法吗?
I'm sorry if this is confusing. 很抱歉,这令人困惑。
UPDATE I'm thinking that the first implementation of CreateTask method may be following. UPDATE我认为可能正在执行CreateTask方法的第一个实现。
class WorkManegementService
{
private TaskRepository taskRepository;
public WorkManegementService(TaskRepository pTaskRepository)
{
taskRepository = pTaskRepository;
}
Guid CreateTask(string name)
{
var taskId = Guid.NewGuid();
var task = new Task(taskId, name, new SystemClock());
try
{
taskRepository.Save(task);
return taskId;
}
catch (...)
{
// some handling
}
}
}
In during further implementation, I'm going to add Task Owner or something similar. 在进一步实施期间,我将添加任务所有者或类似的东西。
You could test the creation and the correct initialization of your object but here there is no real logic to test. 您可以测试对象的创建和正确的初始化,但是这里没有测试的真实逻辑。 It will be better if you have an intention to test in which context this task is used, what behavior.
如果您打算测试在哪个上下文中使用此任务以及什么行为,那就更好了。
Honestly it's unnecessary to unit-test your simple accessors and mutators. 老实说,没有必要对简单的访问器和修改器进行单元测试。 It's a waste of time and it doesn't help anyone.
这是浪费时间,对任何人都没有帮助。 The only reason to test the creation it's because there is a specific state you want your object to be in... (like map of a game or a bank account).
测试创建的唯一原因是因为您希望对象处于特定状态...(例如游戏地图或银行帐户)。
**maybe if you show Create method code it will give a better overview of what your method is supposed to do **也许如果您显示创建方法代码,它将更好地概述您的方法应该做的事情
[Edit] [编辑]
Your test could verify that your save method have been called... 您的测试可以验证您的保存方法已被调用...
repository.Received().Save(Arg.Any<Task>()); // Arg.Is if you prefer
[Edit2] [Edit2]
For the dependencies you could totally delegate the initialization of the task to another method/class, this way your test could be totally predictable and isolated from other dependencies. 对于依赖项,您可以将任务的初始化完全委派给另一个方法/类,这样您的测试就可以完全预测并与其他依赖项隔离。 From a purist point of view, a unit-test should test one thing at the time and have limited reason to fail.
从纯粹的角度来看,单元测试应该同时测试一件事,并且失败的原因有限。 If you are learning I would advise that you apply strictly this rule.
如果您正在学习,我建议您严格应用此规则。
Guid CreateTask(string name)
{
var task = this.InitTask(name); // or factory.CreateTask(name) or you can have public function prop that you inject if you like functional way...
try
{
taskRepository.Save(task);
return taskId;
}
catch (...)
{
// some handling
}
}
The main purpose of unit testing is to ensure the business logic of your application works as expected. 单元测试的主要目的是确保应用程序的业务逻辑按预期工作。 The only business logic you have to test in your example is:
您必须在示例中测试的唯一业务逻辑是:
repository.Save
and the contents of task
are correct repository.Save
并且task
内容正确 As for the Task
object, you might consider testing to ensure the constructor works properly, but it is much more important to unit test your Clock
class to ensure it is working as expected. 对于
Task
对象,您可能考虑进行测试以确保构造函数正常工作,但是对Clock
类进行单元测试以确保其按预期工作更为重要。
Here you ask: 在这里你问:
I have tests for Clock and Task constructor, but it seems that correct execution of CreateTask test depends on Task and Clock classes.
我已经对Clock和Task构造函数进行了测试,但是似乎CreateTask测试的正确执行取决于Task和Clock类。 So the test implicitly covers 3 classes.
因此,测试隐式涵盖了3个类。 Or do I misunderstand that?
还是我误会了?
The Clock
and Task
constructor tests are appropriate, and do not require repetition in CreateTask()
tests. Clock
和Task
构造函数测试是适当的,并且在CreateTask()
测试中不需要重复。
To aggregate the appropriate guidance above, the correct tests for WorkManagementService
are as follows: 为了汇总上面的适当指导,
WorkManagementService
的正确测试如下:
CreateTask()
invocation with a null parameter, then ensure the error is reported as expected (eg, throwing an ArgumentNullException
) CreateTask()
调用, 然后确保按预期报告错误(例如,抛出ArgumentNullException
) CreateTask()
invocation with a good parameter, then ensure repository.Save()
is invoked with the proper parameter (by using a mocked constructor-injected repository) CreateTask()
调用, 然后确保使用正确的参数调用repository.Save()
(通过使用模拟的构造函数注入的存储库) CreateTask()
invocation with a good parameter and a failed repository.Save()
invocation (thrown exception), then ensure CreateTask()
fails as expected (eg, rethrowing the exception, throwing a new outer exception, or some other expected error handling) CreateTask()
调用和一个失败的repository.Save()
调用(引发异常), 然后确保CreateTask()
按预期失败(例如,重新引发异常,引发新的外部异常或其他某些预期的错误)处理) repository.Save()
invocation, then ensure CreateTask()
returns the expected Guid
repository.Save()
调用, 然后确保CreateTask()
返回预期的Guid
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.