- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我是单元测试的新手,感觉我在这里遗漏了一些非常重要的东西。我想在下面测试 DoSomethingWithArray 的结果:
class Traffic:ITraffic
{
private HugeArray _hugeArray;
public Traffic(HugeArray hugeArray)
{
_hugeArray = hugeArray;
}
public int DoSomethingWithArray()
{
var ret = 0;
//Here some code that does something with big array and stores some integer values in ret
return ret;
}
}
class HugeArray
{
//This is my custom data structure;
}
interface ITraffic
{
int DoSomethingWithArray();
}
我正在使用 Nunit,据我所知,模拟接口(interface)比模拟类更好。我的问题是我想测试的是 DosomethingWithArray 在 Traffic 类中的具体功能,我很难概念化 ITraffic 接口(interface)如何适应。我在这里错过了什么?
编辑 下面是我将如何测试我的类(class)
[TestFixture]
public class TrafficTests
{
private Traffic _traffic;
private const int size = 1000000;
private const int key = 1851925790;
[OneTimeSetUp]
public void Setup()
{
var hugeArray = new HugeArray(size);
//Some Setups to create an edge case, not relevant to my question
hugeArray.AddValue(size - 1, Int.MaxValue);
hugeArray.AddValue(size - 2, key);
//This is the object I want to test,
_traffic = new Traffic(hugeArray);
}
[Test]
public void DoSomethingWithArray_Test()
{
Assert.DoesNotThrow(() =>
{
var ret = _traffic.DoSomethingWithArray();
Assert.AreEqual(ret, 233398);
});
}
}
我的问题是:这种方法看起来正确吗?为测试创建的对象是否正常,或者我应该模拟 ITraffic 接口(interface)吗?
最佳答案
在您的示例中,您正在测试 Traffic
的公共(public)方法。 Traffic
实现 ITraffic
无关紧要。如果您从类中删除了 : ITraffic
,那么它就不再实现该接口(interface),它根本不会改变您测试 Traffic
的方式。
您正在测试Traffic
。我们不会 mock 我们正在测试的东西。我们 mock 我们不测试的东西。
假设我有一个验证地址的类:
public class AddressValidator
{
public ValidationResult ValidateAddress(Address address)
{
var result = new ValidationResult();
if(string.IsNullOrEmpty(address.Line1))
result.AddError("Address line 1 is empty.");
if(string.IsNullOrEmpty(address.City))
result.AddError("The city is empty.");
// more validations
return result;
}
}
这个类是否实现接口(interface)并不重要。如果我正在测试此类,则没有什么可模拟的。
假设我意识到我还需要验证邮政编码,但为此我可能需要查询一些外部数据以查看城市是否与邮政编码匹配。可能不同的国家不一样。所以我写了一个新接口(interface)并将其注入(inject)到这个类中:
public interface IPostalCodeValidator
{
ValidationResult ValidatePostalCode(Address address);
}
public class AddressValidator
{
private readonly IPostalCodeValidator _postalCodeValidator;
public AddressValidator(IPostalCodeValidator postalCodeValidator)
{
_postalCodeValidator = postalCodeValidator;
}
public ValidationResult ValidateAddress(Address address)
{
var result = new ValidationResult();
if (string.IsNullOrEmpty(address.Line1))
result.AddError("Address line 1 is empty.");
if (string.IsNullOrEmpty(address.City))
result.AddError("The city is empty.");
var postalCodeValidation = _postalCodeValidator.ValidatePostalCode(address);
if (postalCodeValidation.HasErrors)
result.AddErrors(postalCodeValidation.Errors);
return result;
}
}
邮政编码验证非常复杂,它会在自己的类中进行自己的测试。当我们测试 AddressValidator
时,我们不想测试邮政编码验证器。我们只想隔离测试这个类,单独测试另一个类。在 AddressValidator
中,要确保 _postalCodeValidator.ValidatePostalCode
被调用,如果它返回错误,我们将它们添加到验证结果中。
我们不在这里测试IPostalCodeValidator
(或其实现),所以我们模拟它。例如,使用 Moq :
public void AddressValidator_adds_postal_code_errors()
{
var postalCodeError = new ValidationResult();
postalCodeError.AddError("Bad!");
postalCodeError.AddError("Worse!");
var postalCodeValidatorMock = new Mock<IPostalCodeValidator>();
postalCodeValidatorMock.Setup(x => x.ValidatePostalCode(It.IsAny<Address>()))
.Returns(postalCodeError);
var subject = new AddressValidator(postalCodeValidatorMock.Object);
var result = subject.ValidateAddress(new Address());
Assert.IsTrue(result.Errors.Contains("Bad!"));
Assert.IsTrue(result.Errors.Contains("Worse!"));
}
我们实际上并没有验证邮政编码。我们只是说,为了测试,邮政编码验证器总是会返回这两个错误。然后我们确保 AddressValidator
调用它并执行我们期望它对这些错误执行的操作。
这基本上就是 mock 的内容。这是一个伪造的实现,它做一些简单的事情,比如 jar 头响应,这样我们就可以确保我们按照我们期望的方式处理 jar 头响应。如果 AddressValidator
正确处理了结果,那么它就可以正常工作。完成了。
为确保真实 邮政编码验证器返回正确的结果,我们可以为该类编写测试。这样,每个类(class)都会做一些简单的事情,并进行测试以确保它正确地做事。当我们将它们放在一起时,整个事情更有可能奏效。如果我们破坏 IPostalCodeValidator
的实现,那么该类的测试将失败,但 AddressValidator
的测试仍然会通过。这样我们就可以快速了解哪个部分出现问题,因为它们都是单独测试的,因此我们不必运行和调试大量代码来试图找出问题所在。
关于c# - 模拟界面没有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56636861/
我正在使用 Gunicorn 为 Django 应用程序提供服务,它工作正常,直到我将其超时时间从 30 秒更改为 900000 秒,我不得不这样做,因为我有一个用例需要上传和处理一个巨大的文件(过程
我有一个带有非常基本的管道的Jenkinsfile,它可以旋转docker容器: pipeline { agent { dockerfile { args '-u root' } } stag
在学习 MEAN 堆栈的过程中,我遇到了一个问题。每当我尝试使用 Passport 验证方法时,它都不会返回任何响应。我总是收到“localhost没有发送任何数据。ERR_EMPTY_RESPONS
在当今的大多数企业堆栈中,数据库是我们存储所有秘密的地方。它是安全屋,是待命室,也是用于存储可能非常私密或极具价值的物品的集散地。对于依赖它的数据库管理员、程序员和DevOps团队来说,保护它免受所
是否可以创建像图片上那样的边框?只需使用 css 边框属性。最终结果将是没 Angular 盒子。我不想添加额外的 html 元素。我只想为每个 li 元素添加 css 边框信息。 假设这是一个 ul
我是一名优秀的程序员,十分优秀!